[Wisp-cvs] wisp/users/dig makehello.py,1.18,1.19 elf.py,1.16,1.17
Status: Alpha
Brought to you by:
digg
From: <di...@us...> - 2003-04-08 21:19:11
|
Update of /cvsroot/wisp/wisp/users/dig In directory sc8-pr-cvs1:/tmp/cvs-serv9820 Modified Files: makehello.py elf.py Log Message: moved make_ELF32_executable from makehello.py to elf.py Index: makehello.py =================================================================== RCS file: /cvsroot/wisp/wisp/users/dig/makehello.py,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- makehello.py 3 Apr 2003 09:12:02 -0000 1.18 +++ makehello.py 8 Apr 2003 21:19:05 -0000 1.19 @@ -33,156 +33,8 @@ data.place_symbol('&message') data.emit_string('Hello, world!\n') -def infer_by_prefix (name, dict): - for l in range(len(name), -1, -1): - prefix = name[:l] - try: return dict[prefix] - except: pass - return None -def guess_shtype (name): - return infer_by_prefix(name, {'': SHT.PROGBITS, - '.bss': SHT.NOBITS, - '.dynstr': SHT.STRTAB, - '.note': SHT.NOTE, - '.shstrtab': SHT.STRTAB, - '.symstr': SHT.STRTAB, - '.symtab': SHT.SYMTAB, - }) -def guess_ptype (name): - return infer_by_prefix(name, {'': PT.LOAD, - '.note': PT.NOTE}) -def guess_flags (name): - return infer_by_prefix(name, {'': 'rw--', - '.bss': 'rw--', - '.comment': '----', - '.data': 'rw--', - '.debug': '----', - '.dynstr': 'a--s', - '.line': '----', - '.note': '----', - '.rodata': 'r---', - '.shstrtab': '---s', - '.symstr': 'a--s', - '.text': 'r-x-'}) -def guess_shflags (name): - flags = guess_flags(name) - sh_flags = 0 - if 'r' in flags or 'a' in flags: sh_flags |= SHF.ALLOC - if 'w' in flags: sh_flags |= SHF.ALLOC | SHF.WRITE - if 'x' in flags: sh_flags |= SHF.ALLOC | SHF.EXECINSTR - if 's' in flags: sh_flags |= SHF.STRINGS - return sh_flags -def guess_pflags (name): - flags = guess_flags(name) - p_flags = 0 - if 'r' in flags: p_flags |= PF.R - if 'w' in flags: p_flags |= PF.W - if 'x' in flags: p_flags |= PF.X - return p_flags - -def make_executable (text = None, data = None, - memory_bottom = 0x08048000, - want_symbols = 1): - # Will set given sections' origins. - - sections = {} - sections['.text'] = code - sections['.data'] = data - - binary = Linkie('<') - memory_boundary = memory_bottom # must be at page boundary - binary.paste(0, make_ELF32_header('<')) - binary.place_symbol('#elf/type', ET.EXEC) - binary.place_symbol('#elf/machine', EM.I386) - binary.place_symbol('#elf/flags', 0) # no flags for ia386 - - shentnames = ['.text', '.data'] - if want_symbols: shentnames += ['.symstr', '.symtab'] - shentnames.append('.shstrtab') - - sections['.shstrtab'] = Linkie('<') - sections['.shstrtab'].emit_byte(0) - - if want_symbols: - sections['.symstr'] = Linkie('<') - sections['.symstr'].emit_byte(0) - - sections['.symtab'] = Linkie('<') - sections['.symtab'].align(4) - sections['.symtab'].emit_string('\0' * 16) - - phentnames = [] - for name in shentnames: - if guess_pflags(name) <> 0: - phentnames.append(name) - sections['.shstrtab'].place_symbol('#.shstrtab/strings/' + name) - sections['.shstrtab'].emit_string(name) - sections['.shstrtab'].emit_byte(0) - - program_header_table = make_ELF32_phtable('<', phentnames) - binary.paste(-4, program_header_table) - - for name in shentnames: - section = sections[name] - p_flags = guess_pflags(name) - alignment = section.get_alignment() - binary.place_symbol('#' + name + '/sh_align', alignment) - - if p_flags <> 0: - binary.place_symbol('#' + name + '/p_align', 0x1000) - binary.align(min(alignment, 0x1000)) - else: - # No program header entry => not loaded - # thusly no larger alignment necessary. - binary.align(min(alignment, 4)) - - offset = binary.filesz() - - if p_flags <> 0: - address = memory_boundary | (offset & 0xFFF) - # take into account alignments larger than a page - address = (address + alignment - 1) & ~(alignment - 1) - binary.place_symbol('#' + name + '/p_flags', guess_pflags(name)) - binary.place_symbol('#' + name + '/p_type', guess_ptype(name)) - section.set_origin(address) - binary.place_symbol('&' + name, address) - else: - address = None - - binary.place_symbol('#' + name + '/memsz', section.memsz()) - binary.place_symbol('#' + name + '/filesz', section.filesz()) - binary.place_symbol('#' + name + '/sh_size', section.filesz()) - binary.place_symbol('#' + name + '/sh_type', guess_shtype(name)) - binary.place_symbol('#' + name + '/sh_info', 0) - if name == '.symtab': sh_link = shentnames.index('.symstr') + 1 - else: sh_link = SHN.UNDEF - binary.place_symbol('#' + name + '/sh_link', sh_link) - binary.place_symbol('#' + name + '/sh_entsize', 0) - binary.place_symbol('#' + name + '/sh_flags', guess_shflags(name)) - - # alignment has been processed already - binary.place_symbol('!' + name) - binary.paste(-1, section) - if want_symbols: - symtab = sections['.symtab'] - symstr = sections['.symstr'] - for symbol, value in section.get_symbols(): - if symbol[0] == '&': # only process memory references - emit_ELF32_symtab_entry(symtab, symstr, symbol, value, - shentnames.index(name) + 1) - - memory_boundary += section.memsz() - memory_boundary = (memory_boundary + 0xFFF) & ~0xFFF - - # create section header table - section_header_table = make_ELF32_shtable('<', shentnames) - binary.paste(-4, section_header_table) - binary.place_symbol('#elf/shstrndx', shentnames.index('.shstrtab') + 1) - binary.link() - return binary - print 'With symbols' -hello = make_executable(text = code, data = data) +hello = make_ELF32_executable(text = code, data = data, want_symbols = 1) hello.dump() f = open('hello', 'w') @@ -190,7 +42,7 @@ f.close() print 'Without symbols' -hellowosym = make_executable(text = code, data = data, want_symbols = 0) +hellowosym = make_ELF32_executable(text = code, data = data, want_symbols = 0) hellowosym.dump() f = open('hellowosym', 'w') Index: elf.py =================================================================== RCS file: /cvsroot/wisp/wisp/users/dig/elf.py,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- elf.py 3 Apr 2003 09:12:01 -0000 1.16 +++ elf.py 8 Apr 2003 21:19:06 -0000 1.17 @@ -406,12 +406,160 @@ symtab.emit_byte(0) # st_other; reserved symtab.emit_wyde(section) +def infer_by_prefix (name, dict): + for l in range(len(name), -1, -1): + prefix = name[:l] + try: return dict[prefix] + except: pass + return None + +def guess_ELF32_shtype (name): + return infer_by_prefix(name, {'': SHT.PROGBITS, + '.bss': SHT.NOBITS, + '.dynstr': SHT.STRTAB, + '.note': SHT.NOTE, + '.shstrtab': SHT.STRTAB, + '.symstr': SHT.STRTAB, + '.symtab': SHT.SYMTAB, + }) + +def guess_ELF32_ptype (name): + return infer_by_prefix(name, {'': PT.LOAD, + '.note': PT.NOTE}) + +def guess_ELF32_flags (name): + return infer_by_prefix(name, {'': 'rw--', + '.bss': 'rw--', + '.comment': '----', + '.data': 'rw--', + '.debug': '----', + '.dynstr': 'a--s', + '.line': '----', + '.note': '----', + '.rodata': 'r---', + '.shstrtab': '---s', + '.symstr': 'a--s', + '.text': 'r-x-'}) + +def guess_ELF32_shflags (name): + flags = guess_ELF32_flags(name) + sh_flags = 0 + if 'r' in flags or 'a' in flags: sh_flags |= SHF.ALLOC + if 'w' in flags: sh_flags |= SHF.ALLOC | SHF.WRITE + if 'x' in flags: sh_flags |= SHF.ALLOC | SHF.EXECINSTR + if 's' in flags: sh_flags |= SHF.STRINGS + return sh_flags + +def guess_ELF32_pflags (name): + flags = guess_ELF32_flags(name) + p_flags = 0 + if 'r' in flags: p_flags |= PF.R + if 'w' in flags: p_flags |= PF.W + if 'x' in flags: p_flags |= PF.X + return p_flags + +def make_ELF32_executable (text = None, data = None, + memory_bottom = 0x08048000, + want_symbols = 0): + # Will set given sections' origins. + + sections = {} + sections['.text'] = text + sections['.data'] = data + + binary = Linkie('<') + memory_boundary = memory_bottom # must be at page boundary + binary.paste(0, make_ELF32_header('<')) + binary.place_symbol('#elf/type', ET.EXEC) + binary.place_symbol('#elf/machine', EM.I386) + binary.place_symbol('#elf/flags', 0) # no flags for ia386 + + shentnames = ['.text', '.data'] + if want_symbols: shentnames += ['.symstr', '.symtab'] + shentnames.append('.shstrtab') + + sections['.shstrtab'] = Linkie('<') + sections['.shstrtab'].emit_byte(0) + + if want_symbols: + sections['.symstr'] = Linkie('<') + sections['.symstr'].emit_byte(0) + + sections['.symtab'] = Linkie('<') + sections['.symtab'].align(4) + sections['.symtab'].emit_string('\0' * 16) + + phentnames = [] + for name in shentnames: + if guess_ELF32_pflags(name) <> 0: + phentnames.append(name) + sections['.shstrtab'].place_symbol('#.shstrtab/strings/' + name) + sections['.shstrtab'].emit_string(name) + sections['.shstrtab'].emit_byte(0) + + program_header_table = make_ELF32_phtable('<', phentnames) + binary.paste(-4, program_header_table) + + for name in shentnames: + section = sections[name] + p_flags = guess_ELF32_pflags(name) + alignment = section.get_alignment() + binary.place_symbol('#' + name + '/sh_align', alignment) + + if p_flags <> 0: + binary.place_symbol('#' + name + '/p_align', 0x1000) + binary.align(min(alignment, 0x1000)) + else: + # No program header entry => not loaded + # thusly no larger alignment necessary. + binary.align(min(alignment, 4)) + + offset = binary.filesz() + + if p_flags <> 0: + address = memory_boundary | (offset & 0xFFF) + # take into account alignments larger than a page + address = (address + alignment - 1) & ~(alignment - 1) + binary.place_symbol('#' + name + '/p_flags', guess_ELF32_pflags(name)) + binary.place_symbol('#' + name + '/p_type', guess_ELF32_ptype(name)) + section.set_origin(address) + binary.place_symbol('&' + name, address) + else: + address = None + + binary.place_symbol('#' + name + '/memsz', section.memsz()) + binary.place_symbol('#' + name + '/filesz', section.filesz()) + binary.place_symbol('#' + name + '/sh_size', section.filesz()) + binary.place_symbol('#' + name + '/sh_type', guess_ELF32_shtype(name)) + binary.place_symbol('#' + name + '/sh_info', 0) + if name == '.symtab': sh_link = shentnames.index('.symstr') + 1 + else: sh_link = SHN.UNDEF + binary.place_symbol('#' + name + '/sh_link', sh_link) + binary.place_symbol('#' + name + '/sh_entsize', 0) + binary.place_symbol('#' + name + '/sh_flags', guess_ELF32_shflags(name)) + + # alignment has been processed already + binary.place_symbol('!' + name) + binary.paste(-1, section) + if want_symbols: + symtab = sections['.symtab'] + symstr = sections['.symstr'] + for symbol, value in section.get_symbols(): + if symbol[0] == '&': # only process memory references + emit_ELF32_symtab_entry(symtab, symstr, symbol, value, + shentnames.index(name) + 1) + + memory_boundary += section.memsz() + memory_boundary = (memory_boundary + 0xFFF) & ~0xFFF + + # create section header table + section_header_table = make_ELF32_shtable('<', shentnames) + binary.paste(-4, section_header_table) + binary.place_symbol('#elf/shstrndx', shentnames.index('.shstrtab') + 1) + binary.link() + return binary + # Thoughts of generating ELF32 files # * In ELF parlance, linker notes are called relocations. # We need to solve relocations only when generating an # executable file. -# * ELF symbols are defined relative to their corresponding sections' -# origins. Basically, a symbol's value consists of two parts: -# reference to its section and its location inside the section. -# * We'll need some symbols to represent offsets in the generated -# file. It's probably best to treat them as ELF absolute symbols. |