]> git.alrj.org Git - bold.git/blob - bold.py
First working version.
[bold.git] / bold.py
1 #! /usr/bin/python
2 # -*- coding: utf-8 -*-
3 # kate: space-indent on; indent-width 2; mixedindent off; indent-mode python;
4
5 # Copyright (C) 2009 Amand 'alrj' Tihon <amand.tihon@alrj.org>
6 #
7 # This file is part of bold, the Byte Optimized Linker.
8 # Heavily inspired by elf.h from the GNU C Library.
9 #
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.
13
14 from elf.BinArray import BinArray
15 from elf.constants import *
16 from elf.elf import Elf64, Elf64_Phdr, TextSegment, DataSegment, Dynamic, Interpreter
17 import struct, sys
18
19 infiles = [Elf64(n) for n in sys.argv[1:]]
20 for i in infiles:
21   i.resolve_names()
22   i.find_symbols()
23
24 #h = infile.header
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
42
43 #print "Section header string table index: %s" % h.e_shstrndx
44
45 #print
46
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)
53 #print
54
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)
60     #print
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)
68     #print
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,
76       #i.r_addend)
77     #print
78
79
80
81 outfile = Elf64()
82
83 text_segment = TextSegment()
84 data_segment = DataSegment(align=0x100000)
85
86 outfile.add_segment(text_segment)
87 outfile.add_segment(data_segment)
88
89
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)
94
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)
100
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)
106
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)
111
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)
116
117 interp = Interpreter()
118 text_segment.add_content(interp)
119
120 dynamic = Dynamic()
121 dynamic.add_shlib("libGL.so.1")
122 dynamic.add_shlib("libSDL-1.2.so.0")
123 dynamic.add_symtab(0)
124 dynamic.add_debug()
125 data_segment.add_content(dynamic)
126 text_segment.add_content(dynamic.strtab)
127
128
129 # Find interresting sections in input file
130 for i in infiles:
131   for sh in i.shdrs:
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)
138         else:
139           data_segment.add_content(sh.content)
140
141
142 outfile.layout(base_vaddr=0x400000)
143
144
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
148
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
153
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
158
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
163
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
168
169 for i in infiles:
170   outfile.undefined_symbols.extend(i.undefined_symbols)
171
172 dt_dbg = dynamic.dt_debug_address
173 outfile.global_symbols["_dt_debug"] = dt_dbg
174 outfile.global_symbols["_DYNAMIC"] = dynamic.virt_addr
175
176 # Take all globally declared symbols, and put them in outfile's dict
177 for i in infiles:
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."
183       exit(1)
184     outfile.global_symbols[s] = addr
185
186 for i in infiles:
187   i.apply_relocation(outfile.global_symbols)
188
189 _start = outfile.global_symbols["_start"]
190 outfile.header.e_entry = _start
191
192 # outfile.apply_global_relocation()
193
194 f = open("prout", "wb")
195 outfile.toBinArray().tofile(f)
196 f.close()
197
198
199