@@ -290,6 +290,80 @@ def merge( self, smbl ):
290290 decl .calling_convention = CCTS .extract ( undecorated , CCTS .CDECL )
291291 return decorated , decl
292292
293+ class dylib_file_parser_t ( formated_mapping_parser_t ):
294+ """parser for Darwin .dylib file"""
295+ nm_executable = 'nm'
296+ #numeric-sort used for mapping between mangled and unmangled name
297+ cmd_mangled = ['-c' , '%(nm)s -gfUn %(lib)s | sed "s/ _/ /"' ]
298+ cmd_demangled = ['-c' , '%(nm)s -gfUn %(lib)s | sed "s/ _/ /" | c++filt' ]
299+
300+ entry = re .compile ( r'^(?P<address>(?:\w|\d)+)\s\w\s(?P<symbol>.+)$' )
301+
302+ def __init__ ( self , global_ns , binary_file ):
303+ formated_mapping_parser_t .__init__ ( self , global_ns , binary_file , 'nm' )
304+
305+ def __execute_nm ( self , cmd ):
306+ process = subprocess .Popen ( args = cmd
307+ , stdin = subprocess .PIPE
308+ , stdout = subprocess .PIPE
309+ , stderr = subprocess .STDOUT
310+ , shell = True )
311+ process .stdin .close ()
312+ output = []
313+ while process .poll () is None :
314+ output .append ( process .stdout .readline () )
315+ #the process already finished, read the rest of the output
316+ output .extend ( process .stdout .readlines () )
317+ if process .returncode :
318+ msg = ["Unable to extract public/exported symbols from '%s' file." % self .binary_file ]
319+ msg .append ( 'The command line, which was used to extract symbols, is "%s"' % cmd )
320+ raise RuntimeError ( os .linesep .join (msg ) )
321+ return output
322+
323+ def __extract_symbols ( self , cmd ):
324+ output = self .__execute_nm ( cmd )
325+ result = {}
326+ for line in output :
327+ found = self .entry .match ( line )
328+ if found :
329+ result [ found .group ( 'address' ) ] = found .group ( 'symbol' )
330+ return result
331+
332+ def load_symbols ( self ):
333+ tmpl_args = dict ( nm = self .nm_executable , lib = self .binary_file )
334+ mangled_smbls = self .__extract_symbols ( [part % tmpl_args for part in self .cmd_mangled ] )
335+ demangled_smbls = self .__extract_symbols ( [part % tmpl_args for part in self .cmd_demangled ] )
336+
337+ result = []
338+ for address , blob in mangled_smbls .items ():
339+ if address in demangled_smbls :
340+ result .append ( ( blob , demangled_smbls [address ] ) )
341+ return result
342+
343+ def merge ( self , smbl ):
344+ decorated , undecorated = smbl
345+ if decorated == undecorated :
346+ #we deal with C function ( or may be we deal with variable?, I have to check the latest
347+ try :
348+ f = self .global_ns .free_fun ( decorated )
349+ #TODO create usecase, where C function uses different calling convention
350+ f .calling_convention = CCTS .CDECL
351+ return decorated , f
352+ except self .global_ns .declaration_not_found_t :
353+ v = self .global_ns .vars ( decorated , allow_empty = True , recursive = False )
354+ if v :
355+ return decorated , v [0 ]
356+ else :
357+ return None , None
358+ else :
359+ undecorated_normalized = self .undname_creator .normalize_undecorated ( undecorated )
360+ if undecorated_normalized not in self .formated_decls :
361+ return None , None
362+ decl = self .formated_decls [ undecorated_normalized ]
363+ if isinstance ( decl , declarations .calldef_t ):
364+ decl .calling_convention = CCTS .extract ( undecorated , CCTS .CDECL )
365+ return decorated , decl
366+
293367def merge_information ( global_ns , fname , runs_under_unittest = False ):
294368 """high level function - select the appropriate binary file parser and integrates
295369 the information from the file to the declarations tree. """
@@ -301,6 +375,8 @@ def merge_information( global_ns, fname, runs_under_unittest=False ):
301375 parser = map_file_parser_t ( global_ns , fname )
302376 elif '.so' == ext or '.so.' in os .path .basename (fname ):
303377 parser = so_file_parser_t ( global_ns , fname )
378+ elif '.dylib' == ext :
379+ parser = dylib_file_parser_t ( global_ns , fname )
304380 else :
305381 raise RuntimeError ( "Don't know how to read exported symbols from file '%s'"
306382 % fname )
0 commit comments