Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 #include "common/linux/synth_elf.h" | |
2 | |
3 #include <assert.h> | |
4 #include <elf.h> | |
5 #include <stdio.h> | |
6 | |
7 namespace google_breakpad { | |
8 namespace synth_elf { | |
9 | |
10 ELF::ELF(uint16_t machine, | |
11 Endianness endianness) | |
12 : Section(endianness), | |
13 addr_size_(machine == EM_X86_64 ? 8 : 4), | |
jimb
2011/07/05 19:21:58
There really should be an explicit 'file class' ar
Ted Mielczarek
2011/07/06 15:45:08
I kind of just wanted it to be easy for consumers
| |
14 program_count_(0), | |
15 section_count_(0), | |
16 section_header_table_(endianness), | |
17 section_header_strings_(endianness) { | |
18 // Could add support for more machine types here if needed. | |
19 assert(machine == EM_386 || | |
20 machine == EM_X86_64 || | |
21 machine == EM_ARM); | |
22 | |
23 start() = 0; | |
24 // Add ELF header | |
25 // e_ident | |
26 // EI_MAG0...EI_MAG3 | |
27 D8(ELFMAG0); | |
28 D8(ELFMAG1); | |
29 D8(ELFMAG2); | |
30 D8(ELFMAG3); | |
31 // EI_CLASS | |
32 D8(addr_size_ == 4 ? ELFCLASS32 : ELFCLASS64); | |
33 // EI_DATA | |
34 D8(endianness == kLittleEndian ? ELFDATA2LSB : ELFDATA2MSB); | |
35 // EI_VERSION | |
36 D8(EV_CURRENT); | |
37 // EI_OSABI | |
38 D8(ELFOSABI_SYSV); | |
39 // EI_ABIVERSION | |
40 D8(0); | |
41 // EI_PAD | |
42 Append(7, 0); | |
43 assert(Size() == EI_NIDENT); | |
44 | |
45 // e_type | |
46 D16(ET_EXEC); //TODO: allow passing ET_DYN? | |
47 // e_machine | |
48 D16(machine); | |
49 // e_version | |
50 D32(EV_CURRENT); | |
51 // e_entry | |
52 Append(endianness, addr_size_, 0); | |
53 // e_phoff | |
54 Append(endianness, addr_size_, program_header_label_); | |
55 // e_shoff | |
56 Append(endianness, addr_size_, section_header_label_); | |
57 // e_flags | |
58 D32(0); | |
59 // e_ehsize | |
60 D16(addr_size_ == 8 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr)); | |
61 // e_phentsize | |
62 D16(addr_size_ == 8 ? sizeof(Elf64_Phdr) : sizeof(Elf32_Phdr)); | |
63 // e_phnum | |
64 D16(program_count_label_); | |
65 // e_shentsize | |
66 D16(addr_size_ == 8 ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr)); | |
67 // e_shnum | |
68 D16(section_count_label_); | |
69 // e_shstrndx | |
70 D16(section_header_string_index_); | |
71 | |
72 // Add an empty section for SHN_UNDEF. | |
73 Section shn_undef; | |
74 AddSection("", shn_undef, SHT_NULL); | |
75 } | |
76 | |
77 int ELF::AddSection(const string& name, const Section& section, | |
78 uint32_t type, uint32_t flags, uint64_t addr, | |
79 uint32_t link, uint64_t entsize, uint64_t offset) { | |
80 Label offset_label; | |
81 Label string_label(section_header_strings_.Add(name)); | |
82 size_t size = section.Size(); | |
83 | |
84 int index = section_count_; | |
85 ++section_count_; | |
86 | |
87 section_header_table_ | |
88 // sh_name | |
89 .D32(string_label) | |
90 // sh_type | |
91 .D32(type) | |
92 // sh_flags | |
93 .Append(endianness(), addr_size_, flags) | |
94 // sh_addr | |
95 .Append(endianness(), addr_size_, addr) | |
96 // sh_offset | |
97 .Append(endianness(), addr_size_, offset_label) | |
98 // sh_size | |
99 .Append(endianness(), addr_size_, size) | |
100 // sh_link | |
101 .D32(link) | |
102 // sh_info | |
103 .D32(0) | |
104 // sh_addralign | |
105 .Append(endianness(), addr_size_, 0) | |
106 // sh_entsize | |
107 .Append(endianness(), addr_size_, entsize); | |
108 | |
109 // NULL and NOBITS sections have no content, so they | |
110 // don't need to be written to the file. | |
111 if (type == SHT_NULL) { | |
112 offset_label = 0; | |
113 } else if (type == SHT_NOBITS) { | |
114 offset_label = offset; | |
115 } else { | |
116 Mark(&offset_label); | |
117 Append(section); | |
118 Align(4); | |
119 } | |
120 return index; | |
121 } | |
122 | |
123 void ELF::Finish() { | |
124 // Add the section header string table at the end. | |
125 section_header_string_index_ = section_count_; | |
126 //printf(".shstrtab size: %ld\n", section_header_strings_.Size()); | |
127 AddSection(".shstrtab", section_header_strings_, SHT_STRTAB); | |
128 //printf("section_count_: %ld, sections_.size(): %ld\n", | |
129 // section_count_, sections_.size()); | |
130 section_count_label_ = section_count_; | |
131 program_count_label_ = program_count_; | |
132 // TODO: allow adding entries to program header table | |
133 program_header_label_ = 0; | |
134 | |
135 // Section header table starts here. | |
136 Mark(§ion_header_label_); | |
137 Append(section_header_table_); | |
138 } | |
139 | |
140 SymbolTable::SymbolTable(Endianness endianness, | |
141 size_t addr_size, | |
142 StringTable& table) : Section(endianness), | |
143 addr_size_(addr_size), | |
144 table_(table) { | |
145 assert(addr_size_ == 4 || addr_size_ == 8); | |
146 } | |
147 | |
148 void SymbolTable::AddSymbol(const string& name, uint32_t value, | |
149 uint32_t size, unsigned info, uint16_t shndx) { | |
150 assert(addr_size_ == 4); | |
151 D32(table_.Add(name)); | |
152 D32(value); | |
153 D32(size); | |
154 D8(info); | |
155 D8(0); // other | |
156 D16(shndx); | |
157 } | |
158 | |
159 void SymbolTable::AddSymbol(const string& name, uint64_t value, | |
160 uint64_t size, unsigned info, uint16_t shndx) { | |
161 assert(addr_size_ == 8); | |
162 D32(table_.Add(name)); | |
163 D8(info); | |
164 D8(0); // other | |
165 D16(shndx); | |
166 D64(value); | |
167 D64(size); | |
168 } | |
169 | |
170 } // namespace synth_elf | |
171 } // namespace google_breakpad | |
172 | |
OLD | NEW |