toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.cc

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:0f85a08c154a
1 #include "common/linux/synth_elf.h"
2
3 #include <assert.h>
4 #include <elf.h>
5 #include <stdio.h>
6 #include <string.h>
7
8 #include "common/using_std_string.h"
9
10 namespace google_breakpad {
11 namespace synth_elf {
12
13 #ifndef NT_GNU_BUILD_ID
14 #define NT_GNU_BUILD_ID 3
15 #endif
16
17 ELF::ELF(uint16_t machine,
18 uint8_t file_class,
19 Endianness endianness)
20 : Section(endianness),
21 addr_size_(file_class == ELFCLASS64 ? 8 : 4),
22 program_count_(0),
23 program_header_table_(endianness),
24 section_count_(0),
25 section_header_table_(endianness),
26 section_header_strings_(endianness) {
27 // Could add support for more machine types here if needed.
28 assert(machine == EM_386 ||
29 machine == EM_X86_64 ||
30 machine == EM_ARM);
31 assert(file_class == ELFCLASS32 || file_class == ELFCLASS64);
32
33 start() = 0;
34 // Add ELF header
35 // e_ident
36 // EI_MAG0...EI_MAG3
37 D8(ELFMAG0);
38 D8(ELFMAG1);
39 D8(ELFMAG2);
40 D8(ELFMAG3);
41 // EI_CLASS
42 D8(file_class);
43 // EI_DATA
44 D8(endianness == kLittleEndian ? ELFDATA2LSB : ELFDATA2MSB);
45 // EI_VERSION
46 D8(EV_CURRENT);
47 // EI_OSABI
48 D8(ELFOSABI_SYSV);
49 // EI_ABIVERSION
50 D8(0);
51 // EI_PAD
52 Append(7, 0);
53 assert(Size() == EI_NIDENT);
54
55 // e_type
56 D16(ET_EXEC); //TODO: allow passing ET_DYN?
57 // e_machine
58 D16(machine);
59 // e_version
60 D32(EV_CURRENT);
61 // e_entry
62 Append(endianness, addr_size_, 0);
63 // e_phoff
64 Append(endianness, addr_size_, program_header_label_);
65 // e_shoff
66 Append(endianness, addr_size_, section_header_label_);
67 // e_flags
68 D32(0);
69 // e_ehsize
70 D16(addr_size_ == 8 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr));
71 // e_phentsize
72 D16(addr_size_ == 8 ? sizeof(Elf64_Phdr) : sizeof(Elf32_Phdr));
73 // e_phnum
74 D16(program_count_label_);
75 // e_shentsize
76 D16(addr_size_ == 8 ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr));
77 // e_shnum
78 D16(section_count_label_);
79 // e_shstrndx
80 D16(section_header_string_index_);
81
82 // Add an empty section for SHN_UNDEF.
83 Section shn_undef;
84 AddSection("", shn_undef, SHT_NULL);
85 }
86
87 int ELF::AddSection(const string& name, const Section& section,
88 uint32_t type, uint32_t flags, uint64_t addr,
89 uint32_t link, uint64_t entsize, uint64_t offset) {
90 Label offset_label;
91 Label string_label(section_header_strings_.Add(name));
92 size_t size = section.Size();
93
94 int index = section_count_;
95 ++section_count_;
96
97 section_header_table_
98 // sh_name
99 .D32(string_label)
100 // sh_type
101 .D32(type)
102 // sh_flags
103 .Append(endianness(), addr_size_, flags)
104 // sh_addr
105 .Append(endianness(), addr_size_, addr)
106 // sh_offset
107 .Append(endianness(), addr_size_, offset_label)
108 // sh_size
109 .Append(endianness(), addr_size_, size)
110 // sh_link
111 .D32(link)
112 // sh_info
113 .D32(0)
114 // sh_addralign
115 .Append(endianness(), addr_size_, 0)
116 // sh_entsize
117 .Append(endianness(), addr_size_, entsize);
118
119 sections_.push_back(ElfSection(section, type, addr, offset, offset_label,
120 size));
121 return index;
122 }
123
124 void ELF::AppendSection(ElfSection &section) {
125 // NULL and NOBITS sections have no content, so they
126 // don't need to be written to the file.
127 if (section.type_ == SHT_NULL) {
128 section.offset_label_ = 0;
129 } else if (section.type_ == SHT_NOBITS) {
130 section.offset_label_ = section.offset_;
131 } else {
132 Mark(&section.offset_label_);
133 Append(section);
134 Align(4);
135 }
136 }
137
138 void ELF::AddSegment(int start, int end, uint32_t type, uint32_t flags) {
139 assert(start > 0);
140 assert(size_t(start) < sections_.size());
141 assert(end > 0);
142 assert(size_t(end) < sections_.size());
143 ++program_count_;
144
145 // p_type
146 program_header_table_.D32(type);
147
148 if (addr_size_ == 8) {
149 // p_flags
150 program_header_table_.D32(flags);
151 }
152
153 size_t filesz = 0;
154 size_t memsz = 0;
155 bool prev_was_nobits = false;
156 for (int i = start; i <= end; ++i) {
157 size_t size = sections_[i].size_;
158 if (sections_[i].type_ != SHT_NOBITS) {
159 assert(!prev_was_nobits);
160 // non SHT_NOBITS sections are 4-byte aligned (see AddSection)
161 size = (size + 3) & ~3;
162 filesz += size;
163 } else {
164 prev_was_nobits = true;
165 }
166 memsz += size;
167 }
168
169 program_header_table_
170 // p_offset
171 .Append(endianness(), addr_size_, sections_[start].offset_label_)
172 // p_vaddr
173 .Append(endianness(), addr_size_, sections_[start].addr_)
174 // p_paddr
175 .Append(endianness(), addr_size_, sections_[start].addr_)
176 // p_filesz
177 .Append(endianness(), addr_size_, filesz)
178 // p_memsz
179 .Append(endianness(), addr_size_, memsz);
180
181 if (addr_size_ == 4) {
182 // p_flags
183 program_header_table_.D32(flags);
184 }
185
186 // p_align
187 program_header_table_.Append(endianness(), addr_size_, 0);
188 }
189
190 void ELF::Finish() {
191 // Add the section header string table at the end.
192 section_header_string_index_ = section_count_;
193 //printf(".shstrtab size: %ld\n", section_header_strings_.Size());
194 AddSection(".shstrtab", section_header_strings_, SHT_STRTAB);
195 //printf("section_count_: %ld, sections_.size(): %ld\n",
196 // section_count_, sections_.size());
197 if (program_count_) {
198 Mark(&program_header_label_);
199 Append(program_header_table_);
200 } else {
201 program_header_label_ = 0;
202 }
203
204 for (vector<ElfSection>::iterator it = sections_.begin();
205 it < sections_.end(); ++it) {
206 AppendSection(*it);
207 }
208 section_count_label_ = section_count_;
209 program_count_label_ = program_count_;
210
211 // Section header table starts here.
212 Mark(&section_header_label_);
213 Append(section_header_table_);
214 }
215
216 SymbolTable::SymbolTable(Endianness endianness,
217 size_t addr_size,
218 StringTable& table) : Section(endianness),
219 addr_size_(addr_size),
220 table_(table) {
221 assert(addr_size_ == 4 || addr_size_ == 8);
222 }
223
224 void SymbolTable::AddSymbol(const string& name, uint32_t value,
225 uint32_t size, unsigned info, uint16_t shndx) {
226 assert(addr_size_ == 4);
227 D32(table_.Add(name));
228 D32(value);
229 D32(size);
230 D8(info);
231 D8(0); // other
232 D16(shndx);
233 }
234
235 void SymbolTable::AddSymbol(const string& name, uint64_t value,
236 uint64_t size, unsigned info, uint16_t shndx) {
237 assert(addr_size_ == 8);
238 D32(table_.Add(name));
239 D8(info);
240 D8(0); // other
241 D16(shndx);
242 D64(value);
243 D64(size);
244 }
245
246 void Notes::AddNote(int type, const string &name, const uint8_t* desc_bytes,
247 size_t desc_size) {
248 // Elf32_Nhdr and Elf64_Nhdr are exactly the same.
249 Elf32_Nhdr note_header;
250 memset(&note_header, 0, sizeof(note_header));
251 note_header.n_namesz = name.length() + 1;
252 note_header.n_descsz = desc_size;
253 note_header.n_type = type;
254
255 Append(reinterpret_cast<const uint8_t*>(&note_header),
256 sizeof(note_header));
257 AppendCString(name);
258 Align(4);
259 Append(desc_bytes, desc_size);
260 Align(4);
261 }
262
263 } // namespace synth_elf
264 } // namespace google_breakpad

mercurial