def output_cfi_startstop(label, meta, asm_format): return symbol_with_type(label) \ and meta.get('cfi') == 'yes' \ and meta.get('compiler') == 'gcc' \ and 'text' == section_type(label.section) \ and asm_format in ['att_syntax binutils','intel_syntax','intel_syntax noprefix'] \ and not '3.2.3' in meta.get('data', '')
def new(self, **props): label = self.s.find_symbol(section=self.section, **props) label.insert_bloc() if props.get('bind',None) != 'p2align' \ and 'text' == section_type(self.section) \ and self.section in self.b: self.b[self.section].set_nxt(label) self.b[self.section].set_cfg([label]) self.b[self.section] = label
def mk_asm_footer(label, meta, asm_format): if not symbol_with_type(label): return '' cfi = '' if output_cfi_startstop(label, meta, asm_format): cfi += '\t.cfi_endproc\n' if meta.get('compiler') == 'mingw': return cfi + '' elif meta.get('compiler') == 'clang' and hasattr(label, 'align'): return cfi + '\n' elif 'get_pc_thunk' in str(label): return cfi + '' elif 'text' == section_type(label.section): return cfi + '\t.size\t%s, .-%s\n' % (label.name, label.name) elif label.bind is not None: size = label.bytelen if size != getattr(label, 'size', size): import logging log = logging.getLogger("plasmasm") log.warning("For label %r, computed size is %s", label, size) return cfi + '\t.size\t%s, %s\n' % (label.name, size) NEVER
def mk_bin_file(symbols): import sys symbols.resolve() relocs = {} label_func = [ label for label in symbols.symbols if getattr(label, 'type', None) == 'function' ] if len(label_func): relocs[".eh_frame"] = [] for pos, label, r_type, section in symbols.list_relocs(): if not section in relocs: relocs[section] = [] relocs[section].append((pos, label, r_type)) section_groups = [] sections = [".text", ".data", ".bss"] for label in symbols.symbols: section = getattr(label, 'section', '') if section.startswith(".rodata") and not section in sections: sections.append(section) for label in symbols.symbols: section = getattr(label, 'section', '') if section.startswith(".data") and not section in sections: sections.append(section) for label in symbols.symbols: section = getattr(label, 'section', '') if section.startswith(".text.") and not section in sections: section_groups.append(section) if section in symbols.sections.asm_name: if 'comdat' in symbols.sections.asm_name[section]: sections.insert(0, '.group') sections.append(section) sections += [".comment", ".note.GNU-stack"] if len(label_func): sections += [".eh_frame"] # Creates a relocatable ELF file CPU = symbols.arch.CPU if CPU == 'I386': CPU = '386' from elfesteem import elf, elf_init e = elf_init.ELF(e_type=elf.ET_REL, e_machine=elf.__dict__['EM_' + CPU], sections=sections, relocs=relocs.keys()) # The symbol table, first local and then global and weak # Local symbols begin with an empty symbol and the file name, # then sections until bss, then local object or func, # then other sections, with ".comment" at the end symtab = e.getsectionbyname(".symtab") symtab[0] = elf.Sym32(parent=symtab, name="") symtab_local_file = [] symtab_local_symb = [] symtab_globl_symb = [] for label in symbols.symbols: bind = getattr(label, 'bind', None) if bind in [None, 'weak']: pass elif getattr(label, 'type', None) == 'endofsymbol': pass elif bind == 'file': symtab_local_file.append(label) elif bind == 'local': symtab_local_symb.append(label) elif bind == 'globl': symtab_globl_symb.append(label) else: FAIL symtab_sect = [[]] for v, s in enumerate(e.sh.shlist): if not s.sh.type in [elf.SHT_PROGBITS, elf.SHT_NOBITS]: continue if s.sh.name == '.comment': continue symtab_sect[-1].append( elf.Sym32(parent=symtab, info=elf.STT_SECTION, shndx=v)) if s.sh.name == '.bss': symtab_sect.append([]) symtab_sect.append([]) v = e.sh.shlist.index(e.getsectionbyname(".comment")) symtab_sect[-1].append( elf.Sym32(parent=symtab, info=elf.STT_SECTION, shndx=v)) for v, s in enumerate(e.sh.shlist): if s.sh.name != '.group': continue symtab_sect[-1].append( elf.Sym32(parent=symtab, info=elf.STT_SECTION, shndx=v)) def get_props(label): props = { 'shndx': 0, 'size': getattr(label, 'size', 0), 'value': 0, } props['info'] = { None: elf.STT_NOTYPE, 'object': elf.STT_OBJECT, 'function': elf.STT_FUNC, 'tls_object': elf.STT_TLS, }[getattr(label, 'type', None)] props['other'] = { None: elf.STV_DEFAULT, 'hidden': elf.STV_HIDDEN, }[getattr(label, 'visibility', None)] if not hasattr(label, 'section'): pass elif label.section == comm_symbol_section: props['shndx'] = elf.SHN_COMMON props['value'] = label.align elif label.section.startswith('__'): section = { '__TEXT,__text': '.text', '__DATA,__data': '.data', }[label.section] props['shndx'] = e.sh.shlist.index(e.getsectionbyname(section)) props['value'] = label.address else: section = label.section.split(',')[0] props['shndx'] = e.sh.shlist.index(e.getsectionbyname(section)) props['value'] = label.address return props idx = 1 label_idx = {} for label in symtab_local_file: symtab[idx] = elf.Sym32(parent=symtab, name=label.name, info=elf.STT_FILE, shndx=elf.SHN_ABS) idx += 1 for sym in symtab_sect[0]: symtab[idx] = sym label_idx[e.sh.shlist[sym.shndx].sh.name] = idx idx += 1 for label in symtab_local_symb: props = get_props(label) if props['info'] == elf.STT_NOTYPE: continue symtab[idx] = elf.Sym32(parent=symtab, name=label.name, **props) label_idx[label] = idx idx += 1 for sym in symtab_sect[1]: symtab[idx] = sym label_idx[e.sh.shlist[sym.shndx].sh.name] = idx idx += 1 for label in symtab_local_symb: props = get_props(label) if props['info'] != elf.STT_NOTYPE: continue symtab[idx] = elf.Sym32(parent=symtab, name=label.name, **props) label_idx[label] = idx idx += 1 for sym in symtab_sect[2]: symtab[idx] = sym label_idx[e.sh.shlist[sym.shndx].sh.name] = idx idx += 1 for label in symtab_globl_symb: props = get_props(label) props['info'] |= elf.STB_GLOBAL << 4 symtab[idx] = elf.Sym32(parent=symtab, name=label.name, **props) label_idx[label] = idx idx += 1 for label in symbols.symbols: if getattr(label, 'bind', None) is not None: continue if getattr(label, 'type', None) == 'padding': continue if not label.is_symbol(): continue if label.name.endswith('@PLT') or label.name.endswith('@GOT') \ or label.name.endswith('@GOTOFF'): continue if hasattr(label, 'reference'): continue info = elf.STB_GLOBAL << 4 symtab[idx] = elf.Sym32(parent=symtab, name=label.name, info=info, shndx=0, size=0, value=0) label_idx[label] = idx idx += 1 meta = symbols.get_meta() if 'ident' in meta: s = e.getsectionbyname(".comment") s.content[0] = '\0' + meta['ident'] + '\0' # eh_frame data structure is quite complicated # here, we create a null eh_frame and ad hoc rel.eh_frame if len(label_func): s = e.getsectionbyname(".eh_frame") s.content[0] = '\0' * meta.get('eh_frame_size', 0x18 + 0x20 * len(label_func)) if 'eh_frame_relocs' in meta: eh_reloc = meta['eh_frame_relocs'].sortedkeys else: eh_reloc = [0x20 * (idx + 1) for idx in range(len(label_func))] for idx, pos in enumerate(eh_reloc): if ',' in section: section = label_func[idx].section.split(',')[0] relocs[".eh_frame"].append( (pos, section, (elf.EM_386, elf.R_386_PC32))) # Section relocations from plasmasm.symbols import section_type for section in relocs: s = e.getsectionbyname(".rel" + section) if s is None: continue for idx, (pos, label, r_type) in enumerate(relocs[section]): cpu, info = r_type # For some symbols, the relocation shall refer to the start of # the section, not to the symbol itself. l_sect = getattr(label, 'section', None) if (cpu, info) == (elf.EM_386, elf.R_386_GOTOFF): if section_type(section) == 'text' \ and getattr(label, 'bind', None) == 'local' \ and not label.name.startswith('.LC'): label = l_sect elif not hasattr(label, 'bind'): label = l_sect if (cpu, info) == (elf.EM_386, elf.R_386_32): if not getattr(label, 'bind', None) == 'globl': label = l_sect if (cpu, info) == (elf.EM_386, elf.R_386_PC32): if not getattr(label, 'bind', 'globl') == 'globl': label = l_sect if label in label_idx: info += label_idx[label] << 8 s.content[8 * idx] = elf.Rel32(parent=s, offset=pos, info=info).pack() # Section alignment, does not mimic exactly GNU as align = {'.data': (4, 0), '.bss': (4, 0), '.rodata': (1, 0)} for label in symbols.symbols: section = getattr(label, 'section', None) if not section in align: continue value = getattr(label, 'align', getattr(label, 'size', 0)) al, sz = align[section] for v in [4, 8, 32]: if label.address % v == 0 and al < v <= value: al = v align[section] = (al, sz + value) for section in align: s = e.getsectionbyname(section) if s is None: continue al, sz = align[section] if section == '.data' and al >= sz: continue s.sh.addralign = al # Section content for section in sections: if not section_type(section) in ["text", "data", "rodata", "bss"]: continue s = e.getsectionbyname(section) if s is None: continue if section in [ '.text.__i686.get_pc_thunk.bx', '.text.__i686.get_pc_thunk.cx' ]: for label in symbols.symbols: if not getattr(label, 'section', '').startswith(section): continue s.content[label.address] = label.pack() for o in symbols.object_list(): label = o[0] if label.section != section: continue if hasattr(label, 'align'): end = len(s.content) if (end % label.align) != 0: for c in range(label.align - (end % label.align)): s.content += struct.pack("B", 0) data = struct.pack("") for bloc in o: data += bloc.pack() size = len(data) if hasattr(label, 'size') and label.size != size: log.warning("%s has size %d != %d", label, label.size, size) # This might be cause by p2align directives else: symbols.setattr(name=label.name, size=size) if not hasattr(label, 'address'): log.warning("%s has no address", label) # This should have been addressed by symbols.resolve() label.address = 0 symbols.setattr(name=label.name, address=0) s.content[label.address] = data # Section groups for s in e.sh: if s.sh.type != elf.SHT_GROUP: continue ref = section_groups.pop(0) if 'comdat' in symbols.sections.asm_name.get(ref, ''): s.flags = elf.GRP_COMDAT shndx = e.sh.shlist.index(e.getsectionbyname(ref.split(',')[0])) s.sections = [shndx] if not ',' in ref: # TODO continue label = ref.split(',')[3] s.sh.info = symtab.symtab.index(symtab[label]) return e.pack()
def parse_asm_file(symbols, txt): txt = str(txt.decode('latin1')) # Working with python >= 2.3 bloc = current_blocs(symbols) # Local labels parsing is managed in a specific data structure # https://sourceware.org/binutils/docs-2.18/as/Symbol-Names.html symbols.set_meta(local_labels={}) symbol_type = {} symbol_bind = {} symbol_size = {} cur_align = {} cur_proc = {} in_function = False # - We parse the file line by line, and we build basic blocs # - The end of a basic bloc is either caused by a label or by an # instructions having an impact on the CFG # - In the latter case, a "virtual" numeric label is created lines = list(reversed(txt.split("\n"))) # reverse, to be able to pop/push idx = -1 while len(lines): line = lines.pop() if line.endswith('\r'): line = line[:-1] # e.g. mingw on Windows idx += 1 #comment if re.match(r'\s*;\S*', line): continue if re.match(r'\s*//\S*', line): continue if re.match(r'\s*!\S*', line): continue if re.match(r'\s*#\S*', line): continue #comments put by MacOS X clang compiler r = re.match(r'([^"]*?)\s*(##|# NOREX|# TAILCALL)', line) if r: line = r.groups()[0] #empty if re.match(r'\s*$', line): continue #label r = re.match(r'\s*(\S+)\s*:(.*)', line) if r: symbol = r.groups()[0] lines.append(r.groups()[1]) #labels to forget if re.match(r'\.LL?FB\d+', symbol): in_function = True bloc.set_data_props(LFB=symbol) continue if re.match(r'\.LL?FE\d+', symbol) or \ re.match(r'\.Lfe\d+', symbol): in_function = False continue if re.match(r'\.LL?CFI\d+', symbol) or \ re.match(r'\.LL?VL\d+', symbol) or \ re.match(r'\.LL?BB\d+', symbol) or \ re.match(r'\.LL?BE\d+', symbol) or \ re.match(r'\.LL?LST\d+', symbol) or \ re.match(r'\.LL?ASF\d+', symbol) or \ re.match(r'\.LL?e?text\d+', symbol) or \ re.match(r'\.LL?debug_[a-z]+\d+', symbol): # Symbols added for debugguer continue if symbol_type.get(symbol, '') == 'function': in_function = True if re.match(r'[0-9]+', symbol): # local labels: they are numeric labels, and the syntax nb or nf # is used to make reference to them # https://sourceware.org/binutils/docs-2.18/as/Symbol-Names.html # explains how local labels are converted by GNU as # we use the same technique local = symbols.meta['local_labels'] if not symbol in local: local[symbol] = 0 local[symbol] += 1 symbol = '.L%s\02%d' % (symbol, local[symbol]) props = {'name': symbol} if symbol in symbol_type: props['type'] = symbol_type[symbol] if symbol in symbol_bind: props['bind'] = symbol_bind[symbol] if symbol in symbol_size: props['size'] = symbol_size[symbol] if bloc.section in cur_align: props['align'] = cur_align[bloc.section] if bloc.section in cur_proc: props['proc'] = cur_proc[bloc.section] bloc.new(**props) continue #dollar label r = re.match(r'\s*([0-9]+)\s*\$', line) if r: # https://sourceware.org/binutils/docs-2.18/as/Symbol-Names.html symbol = r.groups()[0] symbol = '.L%s\01%d' % (symbol, len(symbols.symbols)) raise ValueError("Dollar local label %r; not implemented" % symbol) #affect symbol r = re.match(r'\s*(\S+)\s+=\s+(\S+)\s*', line) if r: # seen with clang, rewritten into a .set directive arguments = r.groups() if len(arguments) == 2: dst = symbols.find_symbol(name=arguments[1]) props = {'name': arguments[0]} if hasattr(dst, 'section'): NON_REGRESSION_FOUND props['section'] = dst.section props['data'] = {'set': dst} if props['name'] in symbol_bind: NON_REGRESSION_FOUND props['bind'] = symbol_bind[props['name']] symbols.find_symbol(**props) continue #directive if re.match(r'\s*\.', line): r = re.match(r'\s*\.(\S+)\s*(.*)', line) directive = r.groups()[0] rest = r.groups()[1] #sections if directive in ['section', 'text', 'data', 'bss']: if directive == 'section': if rest.startswith('__TEXT'): symbols.set_meta(container='Mach-O') symbols.set_meta(compiler="clang") if rest.startswith('__DATA'): symbols.set_meta(container='Mach-O') symbols.set_meta(compiler="clang") bloc.section = symbols.sections.parse_attributes(rest) else: bloc.section = '.%s' % directive cur_align.pop(bloc.section, None) continue #other attributes if directive in ['align']: arguments = re.split(r",\W*", rest) cur_align[bloc.section] = int(arguments[0]) if symbols.meta.get('compiler') == 'clang': cur_align[bloc.section] = 1 << cur_align[bloc.section] if len(arguments) > 1: cur_align[bloc.section] = rest # fill = arguments[1] # max = arguments[2] continue if directive in binding_keywords.keys(): symbol_bind[rest] = binding_keywords[directive] continue if directive in ['size']: r = re.match(r'([^,]+),\s*(.+)', rest) symbol = r.groups()[0] size = r.groups()[1] if 'text' == section_type( bloc.section) and size != ".-%s" % symbol: rsz = re.match(r'\.Lfe\d+-%s' % symbol, size) if not rsz: log.warning("Size of %r is %r instead of '.-%s'", symbol, size, symbol) cur_proc.pop(bloc.section, None) if 'text' == section_type(bloc.section): in_function = False continue #symbol_size[symbol] = int(size) continue if directive in ['type']: symbols.set_meta(container='ELF') r = re.match(r'([^,]+),\s*(.+)', rest) symbol = r.groups()[0] type_s = r.groups()[1] if type_s[0] in ['@', '#', '%']: if type_s[0] == '#': symbols.set_meta(format='sparc') type_s = type_s[1:] elif type_s[0] == '"' and type_s[-1] == '"': NON_REGRESSION_FOUND type_s = type_s[1:-1] else: log.error("line %r found in section %s", line, bloc.section) if type_s in section_for_type \ and section_type(bloc.section) in section_for_type[type_s]: if symbol in symbol_type and symbol_type[symbol] != type_s: log.warning("Symbol %s has type %s, not set to %s", symbol, symbol_type[symbol], type_s) else: symbol_type[symbol] = type_s else: log.warning("line %r found in section %s of type %s", line, bloc.section, section_type(bloc.section)) if not symbol in symbol_bind: symbol_bind[symbol] = 'local' continue #data if directive in ['ascii', 'asciz', 'string', 'ustring']: value = line[line.find(r'"') + 1:line.rfind(r'"')] # Decode GNU as representation of strings into python string value = value.replace(r'\\', r'\B') for v in range(0, 4 * 8 * 8): value = value.replace('\\%03o' % v, chr(v)) for v in range(0, 8 * 8): value = value.replace('\\%02o' % v, chr(v)) for v in range(0, 8): value = value.replace('\\%01o' % v, chr(v)) value = value.replace(r'\b', '\b') value = value.replace(r'\t', '\t') value = value.replace(r'\n', '\n') value = value.replace(r'\f', '\f') value = value.replace(r'\r', '\r') value = value.replace(r'\"', '"') value = value.replace(r'\B', '\\') if directive in ['asciz', 'string', 'ustring']: value += "\x00" if directive == 'ustring': NON_REGRESSION_FOUND value = "".join(map(lambda x: x + '\x00', value)) # Convert to bytes, python2 and python3 import struct value = struct.pack("B" * len(value), *[ord(_) for _ in value]) data = ConstantStr(symbols, value, directive) if bloc.section in bloc.b and \ bloc.section in cur_align and \ len(bloc.b[bloc.section].lines) > 0: NON_REGRESSION_FOUND bloc.new(align=cur_align[bloc.section]) bloc.addline(data) cur_align.pop(bloc.section, None) continue if directive in constant_classes.keys(): value = [] for v in re.split(r",\W*", rest): try: v = int(v, 0) except ValueError: pass value.append(v) data = constant_classes[directive](symbols, value) if bloc.section in bloc.b and \ bloc.section in cur_align and \ len(bloc.b[bloc.section].lines) > 0: bloc.new(align=cur_align[bloc.section]) bloc.addline(data) cur_align.pop(bloc.section, None) continue if directive in ['zero', 'space']: r = re.match(r'([^,]+),\s*([^,]+)', rest) if r is None: data = ConstantZero(symbols, int(rest)) else: # .space second argument is the padding value r = r.groups() size = r[0] padding = r[1] data = Constant1Byte(symbols, [int(padding)] * int(size)) bloc.addline(data) cur_align.pop(bloc.section, None) continue if directive in ['comm', 'common', 'lcomm', 'tls_common']: r = re.match(r'([^,]+),\s*([^,]+),\s*(.+)', rest) if r is None: r = re.match(r'([^,]+),\s*(.+)\s*# (\d+)', rest) symbols.set_meta(compiler="mingw") if r is None: r = re.match(r'([^,]+),\s*(.+)', rest) r = r.groups() symbol = r[0] size = int(r[1]) if len(r) == 3: align = int(r[2]) if symbols.meta.get('compiler') == 'clang': align = 1 << align else: # mingw align = None bind = symbol_bind.get(symbol, 'globl') props = { 'section': comm_symbol_section, 'bind': bind, 'size': size, 'align': align } if directive == 'tls_common': NON_REGRESSION_FOUND props['type'] = 'tls_object' l = symbols.find_symbol(name=symbol, **props) l.insert_bloc() data = ConstantZero(symbols, size) l.addline(data) continue if directive == 'zerofill': rest = re.split(",", rest) if not rest[0] == '__DATA': raise ValueError("zerofill not in __DATA but %s" % rest[0]) section = "%s,%s" % (rest[0], rest[1]) symbol = rest[2] bind = symbol_bind.get(symbol, 'local') size = int(rest[3]) align = int(rest[4]) # Note that the actual alignment is 2**align align = 1 << align props = { 'section': section, 'bind': bind, 'size': size, 'align': align } symbols.sections.set_asm_name(section, section + ",(zerofill)") l = symbols.find_symbol(name=symbol, **props) l.insert_bloc() data = ConstantZero(symbols, props['size']) l.addline(data) continue #other if directive == 'intel_syntax': if rest == '': format = 'intel_syntax' if rest == 'noprefix': format = 'intel_syntax noprefix' symbols.set_meta(format=format) continue if directive == 'file': if rest[0] == '"' and rest[-1] == '"': rest = rest[1:-1] elif re.match(r'\d+ ".+"', rest): # Info added for debugguer continue else: log.error("%s name %r is not between quotes", directive, rest) symbols.find_symbol(name=rest, bind="file") continue if directive == 'ident': if rest[0] == '"' and rest[-1] == '"': rest = rest[1:-1] else: log.error("%s name %r is not between quotes", directive, rest) symbols.set_meta(ident=rest) if rest.startswith("GCC: ") and symbols.get_meta().get( 'compiler', None) != 'mingw': symbols.set_meta(compiler='gcc') continue if directive == 'def': symbols.set_meta(container='PE') symbols.set_meta(compiler="mingw") r = re.match(r'([^;]+);\s*(.+);\t.endef', rest) symbol = r.groups()[0] param = r.groups()[1] param = dict([x.split('\t') for x in param.split(';\t')]) if '.type' in param and param['.type'] == '32': symbol_type[symbol] = 'function' if '.scl' in param and param['.scl'] == '2': symbol_bind[symbol] = 'globl' if '.scl' in param and param['.scl'] == '3': symbol_bind[symbol] = 'local' props = {'name': symbol} if symbol in symbol_type: props['type'] = symbol_type[symbol] if symbol in symbol_bind: props['bind'] = symbol_bind[symbol] if symbol in symbol_size: props['size'] = symbol_size[symbol] symbols.find_symbol(**props) continue if directive == 'proc': cur_proc[bloc.section] = rest # SPARC only, unused continue if directive == 'loc': # Helper for debugging continue if directive == 'indirect_symbol': # Mach-O specific bloc.set_data_props(**{directive: rest}) continue if directive == 'subsections_via_symbols': symbols.set_meta(compiler="clang") continue if directive == 'macosx_version_min': # Older versions of clang, e.g. clang-900 symbols.set_meta(compiler="clang") r = re.match(r'([0-9]+),\s*([0-9]+)', rest) if r is not None: r = r.groups() osmaj = int(r[0]) osmin = int(r[1]) symbols.set_meta(os_minversion=(osmaj, osmin, 'vermin')) continue if directive == 'build_version': # Recent versions of clang, e.g. clang-1001 symbols.set_meta(compiler="clang") r = re.match(r'macos, ([0-9]+),\s*([0-9]+)', rest) if r is not None: r = r.groups() osmaj = int(r[0]) osmin = int(r[1]) symbols.set_meta(os_minversion=(osmaj, osmin, 'bldver')) continue if directive in ('data_region', 'end_data_region'): # Recent versions of clang, e.g. clang-801 symbols.set_meta(compiler="clang") continue if directive in [ 'hidden', 'protected', 'internal', 'private_extern', 'weak_def_can_be_hidden' ]: symbols.find_symbol(name=rest) symbols.setattr(name=rest, visibility=directive) continue if directive.startswith('cfi_'): if directive in ['cfi_personality', 'cfi_lsda']: bloc.set_data_props(**{directive: rest}) if directive in ['cfi_sections']: symbols.set_meta(**{directive: rest}) symbols.set_meta(cfi='yes') continue if directive == 'p2align': if not in_function: props = {'bind': 'p2align', 'type': 'padding'} if bloc.section in cur_align: props['align'] = cur_align[bloc.section] cur_align.pop(bloc.section, None) bloc.new(**props) line = ".p2align %s" % rest data = P2Align(symbols, line) bloc.addline(data) continue if directive == 'symver': # Syntax: weakref symbol, alias arguments = re.split(r",\W*", rest) if len(arguments) == 2: dst = symbols.find_symbol(name=arguments[1]) props = {'name': arguments[0]} props['data'] = {'symver': dst} symbols.find_symbol(**props) continue if directive == 'weakref': # Syntax: weakref alias, symbol # Renames alias as symbol, that will be its external name arguments = re.split(r",\W*", rest) if len(arguments) == 2: dst = symbols.find_symbol(name=arguments[0]) props = {'name': arguments[1]} props['data'] = {'weakref': dst} symbols.find_symbol(**props) continue if directive == 'set': # Syntax: set symbol, expression # Defines a new symbol, with an expression # Same symbol section, address and type # binding and size can be different arguments = re.split(r",\W*", rest) if len(arguments) == 2: dst = symbols.find_symbol(name=arguments[1]) props = {'name': arguments[0]} props['data'] = {'set': dst} if props['name'] in symbol_bind: props['bind'] = symbol_bind[props['name']] symbols.find_symbol(**props) continue if directive == 'linkonce': # The current section has a linkonce directive # Only for PE NON_REGRESSION_FOUND symbols.sections.add_attribute( bloc.section, "\n\t.%s\t%s" % (directive, rest)) continue raise ValueError("unknown directive %s" % str(directive)) #code if ';' in line: lines.append(line[line.find(';') + 1:]) line = line[:line.find(';')] data = Instruction(symbols).from_txt(line) bloc.addline(data) cur_align.pop(bloc.section, None) for name in symbol_bind: if not name in symbols.symbols_byname: symbols.find_symbol(name=name, bind=symbol_bind[name]) if not 'compiler' in symbols.meta: # Heuristics to choose between gcc, mingw, clang if not len(symbols.symbols): symbols.set_meta(compiler='gcc') else: for label in symbols.symbols: if getattr(label, 'bind', None) != 'file' and \ not label.name.startswith('_'): symbols.set_meta(compiler='gcc') break else: symbols.set_meta(compiler='mingw')