2 # -*- coding: utf-8 -*-
3 # kate: space-indent on; indent-width 2; mixedindent off; indent-mode python;
5 # Copyright (C) 2009 Amand 'alrj' Tihon <amand.tihon@alrj.org>
7 # This file is part of bold, the Byte Optimized Linker.
8 # Heavily inspired by elf.h from the GNU C Library.
10 # You can redistribute this file and/or modify it under the terms of the
11 # GNU Lesser General Public License as published by the Free Software
12 # Foundation, version 2.1.
14 from elf.BinArray import BinArray
15 from elf.constants import *
16 from elf.elf import Elf64, Elf64_Phdr, TextSegment, DataSegment, Dynamic, Interpreter
19 infiles = [Elf64(n) for n in sys.argv[1:]]
25 #print "Class: %s" % h.e_ident.ei_class
26 #print "Data: %s" % h.e_ident.ei_data
27 #print "Version: %s" % h.e_ident.ei_version
28 #print "OS/ABI: %s" % h.e_ident.ei_osabi
29 #print "ABI Version: %s" % h.e_ident.ei_abiversion
30 #print "Type: %s" % h.e_type
31 #print "Machine: %s" % h.e_machine
32 #print "Version: %s" % h.e_version
33 #print "Entry point address: 0x%x" % h.e_entry
34 #print "Start of program headers: %i (bytes into file)" % h.e_phoff
35 #print "Start of section headers: %i (bytes into file)" % h.e_shoff
36 #print "Flags: 0x%x" % h.e_flags
37 #print "Size of this header: %i (bytes)" % h.e_ehsize
38 #print "Size of program headers: %i (bytes)" % h.e_phentsize
39 #print "Number of program headers: %i" % h.e_phnum
40 #print "Size of section headers: %i (bytes)" % h.e_shentsize
41 #print "Number of section headers: %i" % h.e_shnum
43 #print "Section header string table index: %s" % h.e_shstrndx
47 #print "Section Headers:"
48 #for sh in infile.shdrs:
49 #print "[%2i] %-16s %-16s %016x %08x" % (sh.index, sh.name, sh.sh_type,
50 #sh.sh_addr, sh.sh_offset)
51 #print " %016x %016x %-5s %4i %4i %4i" % (sh.sh_size, sh.sh_entsize,
52 #sh.sh_flags, sh.sh_link, sh.sh_info, sh.sh_addralign)
55 #for sh in infile.shdrs :
56 #if sh.sh_type == SHT_STRTAB:
57 ##print "Section %i is a string table with entries :" % sh.index
58 ##for i, name in sh.content.iteritems():
59 ## print "%4i %s" % (i, name)
61 #elif sh.sh_type == SHT_SYMTAB:
62 #print "Section %i is a symbol table with entries :" % sh.index
63 #print " Num: Value Size Type Bind Vis Ndx Name"
64 #for i, sym in enumerate(sh.content.symtab):
65 #print "%6i: %016x %5s %-7s %-6s %-7s %4s %s" % (i,
66 #sym.st_value, sym.st_size, sym.st_type, sym.st_binding,
67 #sym.st_visibility, sym.st_shndx, sym.name)
69 #elif sh.sh_type == SHT_RELA:
70 #print "Section %s is a RELA that applies to %s:" % (sh.name, sh.target.name)
71 #print " Offset Info Type Sym. Value Sym. Name + Addend"
72 #for i in sh.content.relatab:
73 #print "%012x %012x %-16s %016x %s%s + %x" % (i.r_offset, i.r_info,
74 #i.r_type, i.symbol.st_value, i.symbol.name,
75 #sh.owner.shdrs[i.symbol.st_shndx].name,
83 text_segment = TextSegment()
84 data_segment = DataSegment(align=0x100000)
86 outfile.add_segment(text_segment)
87 outfile.add_segment(data_segment)
90 outfile.header.e_ident.make_default_amd64()
91 outfile.header.e_phoff = outfile.header.size
92 outfile.header.e_type = ET_EXEC
93 text_segment.add_content(outfile.header)
95 ph_text = Elf64_Phdr()
96 ph_text.p_type = PT_LOAD
97 ph_text.p_align = 0x100000
98 outfile.add_phdr(ph_text)
99 text_segment.add_content(ph_text)
101 ph_data = Elf64_Phdr()
102 ph_data.p_type = PT_LOAD
103 ph_data.p_align = 0x100000
104 outfile.add_phdr(ph_data)
105 text_segment.add_content(ph_data)
107 ph_dynamic = Elf64_Phdr()
108 ph_dynamic.p_type = PT_DYNAMIC
109 outfile.add_phdr(ph_dynamic)
110 text_segment.add_content(ph_dynamic)
112 ph_interp = Elf64_Phdr()
113 ph_interp.p_type = PT_INTERP
114 outfile.add_phdr(ph_interp)
115 text_segment.add_content(ph_interp)
117 interp = Interpreter()
118 text_segment.add_content(interp)
121 dynamic.add_shlib("libGL.so.1")
122 dynamic.add_shlib("libSDL-1.2.so.0")
123 dynamic.add_symtab(0)
125 data_segment.add_content(dynamic)
126 text_segment.add_content(dynamic.strtab)
129 # Find interresting sections in input file
132 if (sh.sh_flags & SHF_ALLOC):
133 if (sh.sh_flags & SHF_EXECINSTR):
134 text_segment.add_content(sh.content)
135 else: # No exec, it's for .data
136 if (sh.sh_type == SHT_NOBITS):
137 data_segment.add_nobits(sh.content)
139 data_segment.add_content(sh.content)
142 outfile.layout(base_vaddr=0x400000)
145 # Set addresses, sizes, etc. where known
146 outfile.header.e_phnum = len(outfile.phdrs)
147 outfile.header.e_phoff = outfile.phdrs[0].file_offset
149 ph_text.p_offset = text_segment.file_offset
150 ph_text.p_vaddr = text_segment.virt_addr
151 ph_text.p_filesz = text_segment.physical_size
152 ph_text.p_memsz = text_segment.logical_size
154 ph_data.p_offset = data_segment.file_offset
155 ph_data.p_vaddr = data_segment.virt_addr
156 ph_data.p_filesz = data_segment.physical_size
157 ph_data.p_memsz = data_segment.logical_size
159 ph_interp.p_offset = interp.file_offset
160 ph_interp.p_vaddr = interp.virt_addr
161 ph_interp.p_filesz = interp.physical_size
162 ph_interp.p_memsz = interp.logical_size
164 ph_dynamic.p_offset = dynamic.file_offset
165 ph_dynamic.p_vaddr = dynamic.virt_addr
166 ph_dynamic.p_filesz = dynamic.physical_size
167 ph_dynamic.p_memsz = dynamic.logical_size
170 outfile.undefined_symbols.extend(i.undefined_symbols)
172 dt_dbg = dynamic.dt_debug_address
173 outfile.global_symbols["_dt_debug"] = dt_dbg
174 outfile.global_symbols["_DYNAMIC"] = dynamic.virt_addr
176 # Take all globally declared symbols, and put them in outfile's dict
178 for s in i.global_symbols:
179 section_addr = i.global_symbols[s][0].content.virt_addr
180 addr = section_addr + i.global_symbols[s][1]
181 if s in outfile.global_symbols:
182 print "Symbol '%s' defined more than once."
184 outfile.global_symbols[s] = addr
187 i.apply_relocation(outfile.global_symbols)
189 _start = outfile.global_symbols["_start"]
190 outfile.header.e_entry = _start
192 # outfile.apply_global_relocation()
194 f = open("prout", "wb")
195 outfile.toBinArray().tofile(f)