|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * |
|
5 * This program is free software: you can redistribute it and/or modify |
|
6 * it under the terms of the GNU Lesser General Public License as published by |
|
7 * the Free Software Foundation, either version 3 of the License, or |
|
8 * (at your option) any later version. |
|
9 * |
|
10 * This program is distributed in the hope that it will be useful, |
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13 * GNU Lesser General Public License for more details. |
|
14 * |
|
15 * You should have received a copy of the GNU Lesser General Public License |
|
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
17 */ |
|
18 |
|
19 #include <fcntl.h> |
|
20 #include <string.h> |
|
21 #include <iostream> |
|
22 #include <sstream> |
|
23 #include <iomanip> |
|
24 |
|
25 using namespace std; |
|
26 |
|
27 #include "elfromerror.h" |
|
28 #include "elfrom.h" |
|
29 #include "inputfile.h" |
|
30 |
|
31 #define NO_GAPS |
|
32 |
|
33 void ElfRom::SetupE32RomData() { |
|
34 SetupRomElf32_EHdr(); |
|
35 SetupRomImage(); |
|
36 } |
|
37 |
|
38 // TODO: don't use primary file - fill header in by hand. |
|
39 void ElfRom::SetupRomElf32_EHdr() { |
|
40 //create ELF header |
|
41 |
|
42 unsigned char c[EI_NIDENT] = {ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, ELFCLASS32, ELFDATA2LSB, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
|
43 Elf32_Ehdr elf32_ehdr; |
|
44 |
|
45 for (int i=0; i <EI_NIDENT;i++) |
|
46 elf32_ehdr.e_ident[i] = c[i]; |
|
47 |
|
48 elf32_ehdr.e_type = ET_EXEC; |
|
49 elf32_ehdr.e_machine = EM_ARM; |
|
50 elf32_ehdr.e_version = EV_CURRENT; |
|
51 elf32_ehdr.e_entry = iRomDetails->iRomPhysAddr; |
|
52 elf32_ehdr.e_shoff = sizeof(Elf32_Ehdr); |
|
53 |
|
54 // ARM specific flags |
|
55 // e_entry contains a program-loader entry point |
|
56 #define EF_ARM_HASENTRY 0x02 |
|
57 // Each subsection of the symbol table is sorted by symbol value |
|
58 #define EF_ARM_SYMSARESORTED 0x04 |
|
59 // Symbols in dynamic symbol tables that are defined in sections |
|
60 // included in program segment n have st_shndx = n+ 1. |
|
61 #define EF_ARM_DYNSYMSUSESEGIDX 0x8 |
|
62 // Mapping symbols precede other local symbols in the symbol table |
|
63 #define EF_ARM_MAPSYMSFIRST 0x10 |
|
64 // This masks an 8-bit version number, the version of the ARM EABI to |
|
65 // which this ELF file conforms. This EABI is version 2. A value of 0 |
|
66 // denotes unknown conformance. (current version is 0x02000000) |
|
67 #define EF_ARM_EABIMASK 0xFF000000 |
|
68 |
|
69 #define EF_ARM_EABI_VERSION 0x02000000 |
|
70 #define EF_ARM_BPABI_VERSION 0x04000000 |
|
71 |
|
72 elf32_ehdr.e_flags = EF_ARM_BPABI_VERSION | EF_ARM_HASENTRY; |
|
73 elf32_ehdr.e_ehsize = sizeof(Elf32_Ehdr); |
|
74 elf32_ehdr.e_phentsize = sizeof(Elf32_Phdr); |
|
75 elf32_ehdr.e_shentsize = sizeof(Elf32_Shdr); |
|
76 elf32_ehdr.e_shnum = 0; |
|
77 elf32_ehdr.e_shstrndx = 0; |
|
78 elf32_ehdr.e_phnum = 02; |
|
79 new (&iElf32Header) Elf32Header(elf32_ehdr); |
|
80 #if 0 |
|
81 iElf32Header.SetEntryPoint(iRomDetails->iRomPhysAddr); |
|
82 elf_end(e); |
|
83 close(fd); |
|
84 #endif |
|
85 iElf32Header.SetEntryPoint(iRomDetails->iRomPhysAddr); |
|
86 iElf32Header.AddData(iOutputFile); |
|
87 assert(iElf32Header.GetOffset() == 0); |
|
88 if (iRomDetails->iTrace){ |
|
89 cout << "\nElf header added.\n"; |
|
90 } |
|
91 |
|
92 } |
|
93 |
|
94 |
|
95 void ElfRom::SetupRomImage(){ |
|
96 // ensure image size is known and we know how to get hold of it |
|
97 iE32RomImage.SetupRomData(); |
|
98 iE32RomImage.AddData(iOutputFile); |
|
99 assert(iE32RomImage.GetOffset() == iElf32Header.Size()); |
|
100 if (iRomDetails->iTrace){ |
|
101 size_t offset = iE32RomImage.GetOffset(); |
|
102 size_t size = iE32RomImage.Size(); |
|
103 cout << "\nAdded ROM image " << iRomDetails->iRomFile << "\n"; |
|
104 cout.fill('0'); |
|
105 cout << hex << " offset 0x" << setw(8) |
|
106 << offset << " size = 0x" << setw(8) << size << "\n" ; |
|
107 } |
|
108 } |
|
109 |
|
110 void ElfRom::SetupProgramHeaderTable(){ |
|
111 size_t offsetx = AddBootStrapProgramHeader(); |
|
112 RomDetails::XIPFileList::iterator aXIPFile = iRomDetails->iXIPFiles.begin(); |
|
113 RomDetails::XIPFileList::iterator end = iRomDetails->iXIPFiles.end(); |
|
114 unsigned int p = iRomDetails->iRomPhysAddr; |
|
115 unsigned int v = iRomDetails->iRomBaseLinearAddr; |
|
116 int addend = v > p ? -(v - p) : p - v; |
|
117 |
|
118 if (iRomDetails->iTrace){ |
|
119 cout << "\nAdding program headers for e32images\n"; |
|
120 } |
|
121 |
|
122 while (aXIPFile != end) { |
|
123 offsetx = SetupProgramHeaders(*aXIPFile, offsetx, addend); |
|
124 aXIPFile++; |
|
125 } |
|
126 AddFinalHeader(offsetx); |
|
127 |
|
128 #ifdef NO_GAPS |
|
129 // check there are no gaps or overlaps in the phdrs |
|
130 Elf32_Word bsz = iBootStrapPHdr.GetPhdrFilesz(); |
|
131 Elf32_Word coffset = iBootStrapPHdr.GetPhdrOffset() + bsz; |
|
132 Elf32_Addr phys_addr = iBootStrapPHdr.GetPhdrPaddr() + bsz; |
|
133 ElfPHdrList::iterator aCheckHdr = iElfPHdrList.begin(); |
|
134 ElfPHdrList::iterator endCheckHdr = iElfPHdrList.end(); |
|
135 while(aCheckHdr != endCheckHdr) { |
|
136 Elf32_Word o = aCheckHdr->GetPhdrOffset(); |
|
137 if (coffset != o){ |
|
138 cerr << "Error: Phdr table broken - offsets incorrect\n"; |
|
139 assert(coffset == o); |
|
140 } |
|
141 Elf32_Addr addr = aCheckHdr->GetPhdrPaddr(); |
|
142 if (phys_addr > addr){ |
|
143 cerr << "Error: Phdr table broken - physical addresses incorrect\n"; |
|
144 assert(phys_addr <= addr); |
|
145 } |
|
146 size_t sz = aCheckHdr->GetPhdrFilesz(); |
|
147 coffset = o + sz; |
|
148 phys_addr = addr + sz; |
|
149 aCheckHdr++; |
|
150 } |
|
151 #endif |
|
152 |
|
153 ElfPHdrList::iterator aHdr = iElfPHdrList.begin(); |
|
154 ElfPHdrList::iterator endHdr = iElfPHdrList.end(); |
|
155 while (aHdr != endHdr) { |
|
156 aHdr->AddData(iOutputFile); |
|
157 aHdr++; |
|
158 } |
|
159 } |
|
160 |
|
161 size_t ElfRom::AddBootStrapProgramHeader(){ |
|
162 iBootStrapPHdr.SetPhdrType(PT_LOAD); |
|
163 iBootStrapPHdr.SetPhdrOffset(iE32RomImage.GetOffset()); |
|
164 iBootStrapPHdr.SetPhdrVaddr(iRomDetails->iRomPhysAddr); |
|
165 iBootStrapPHdr.SetPhdrPaddr(iRomDetails->iRomPhysAddr); |
|
166 iBootStrapPHdr.SetPhdrAlign(4); |
|
167 iBootStrapPHdr.SetPhdrFlags(PF_X + PF_R); |
|
168 size_t bootstrapsize = iRomDetails->iXIPFiles[0].iLoadAddr - iRomDetails->iRomBaseLinearAddr; |
|
169 iBootStrapPHdr.SetPhdrFilesz(bootstrapsize); |
|
170 iBootStrapPHdr.SetPhdrMemsz(bootstrapsize); |
|
171 |
|
172 iBootStrapPHdr.AddData(iOutputFile); |
|
173 assert((iElf32Header.Size() + iE32RomImage.Size()) == iBootStrapPHdr.GetOffset()); |
|
174 iElf32Header.AddProgramHdr(); |
|
175 iElf32Header.SetProgramHdrOffset(iBootStrapPHdr.GetOffset()); |
|
176 if (iRomDetails->iTrace){ |
|
177 size_t offset = iBootStrapPHdr.GetOffset(); |
|
178 cout << "\nAdded PHdr for bootstrap\n"; |
|
179 cout.fill('0'); |
|
180 cout << hex << " offset 0x" << setw(8) << offset |
|
181 << " size = 0x" << setw(8) << bootstrapsize << "\n"; |
|
182 } |
|
183 |
|
184 return iE32RomImage.GetOffset() + bootstrapsize; |
|
185 } |
|
186 |
|
187 static inline size_t InitE32HdrPHdr(ElfPHdr & hdr, size_t offset, Elf32_Word vaddr, Elf32_Word paddr, Elf32_Word size){ |
|
188 hdr.SetPhdrType(PT_LOAD); |
|
189 hdr.SetPhdrOffset(offset); |
|
190 hdr.SetPhdrVaddr(vaddr); |
|
191 hdr.SetPhdrPaddr(paddr); |
|
192 hdr.SetPhdrAlign(0); |
|
193 hdr.SetPhdrFlags(PF_R); |
|
194 hdr.SetPhdrFilesz(size); |
|
195 hdr.SetPhdrMemsz(size); |
|
196 |
|
197 return offset + size; |
|
198 |
|
199 } |
|
200 static inline size_t InitROPHdr(ElfPHdr & hdr, size_t offset, Elf32_Word vaddr, Elf32_Word paddr, Elf32_Word size){ |
|
201 hdr.SetPhdrType(PT_LOAD); |
|
202 hdr.SetPhdrOffset(offset); |
|
203 hdr.SetPhdrVaddr(vaddr); |
|
204 hdr.SetPhdrPaddr(paddr); |
|
205 hdr.SetPhdrAlign(4); |
|
206 hdr.SetPhdrFlags(PF_X + PF_R); |
|
207 hdr.SetPhdrFilesz(size); |
|
208 hdr.SetPhdrMemsz(size); |
|
209 |
|
210 return offset + size; |
|
211 |
|
212 } |
|
213 |
|
214 static inline size_t InitRWPHdr(ElfPHdr & hdr, size_t offset, Elf32_Word vaddr, Elf32_Word paddr, Elf32_Word fsize, Elf32_Word msize){ |
|
215 hdr.SetPhdrType(PT_LOAD); |
|
216 hdr.SetPhdrOffset(offset); |
|
217 hdr.SetPhdrVaddr(vaddr); |
|
218 hdr.SetPhdrPaddr(paddr); |
|
219 hdr.SetPhdrAlign(4); |
|
220 hdr.SetPhdrFlags(PF_X + PF_R); |
|
221 hdr.SetPhdrFilesz(fsize); |
|
222 hdr.SetPhdrMemsz(msize); |
|
223 |
|
224 return offset + fsize; |
|
225 |
|
226 } |
|
227 |
|
228 size_t ElfRom::SetupProgramHeaders(XIPFileDetails & aXIPFileDetails, size_t offset, int addend){ |
|
229 ElfPHdr e32hdr; |
|
230 Elf32_Word e32hdrVaddr = aXIPFileDetails.iLoadAddr; |
|
231 Elf32_Word e32hdrPaddr = aXIPFileDetails.iLoadAddr + addend; |
|
232 Elf32_Word e32hdrSize = aXIPFileDetails.iROAddr - aXIPFileDetails.iLoadAddr ; |
|
233 size_t e32hdrOffsetInRom = aXIPFileDetails.iLoadAddr - iRomDetails->iRomBaseLinearAddr; |
|
234 size_t e32hdrOffsetInElf = iE32RomImage.GetOffset() + e32hdrOffsetInRom; |
|
235 #ifdef NO_GAPS |
|
236 // But actually the offset we'll use is the one we were given as an argument. |
|
237 // This means we need to adjust the size, vaddr and paddr by the difference |
|
238 size_t diff = e32hdrOffsetInElf - offset; |
|
239 e32hdrSize += diff; |
|
240 e32hdrVaddr -= diff; |
|
241 e32hdrPaddr -= diff; |
|
242 offset = InitE32HdrPHdr(e32hdr, offset, e32hdrVaddr, e32hdrPaddr, e32hdrSize); |
|
243 #else |
|
244 offset = InitE32HdrPHdr(e32hdr, e32hdrOffsetInElf, e32hdrVaddr, e32hdrPaddr, e32hdrSize); |
|
245 #endif |
|
246 iElf32Header.AddProgramHdr(); |
|
247 iElfPHdrList.push_back(e32hdr); |
|
248 ElfPHdr thdr; |
|
249 Elf32_Word textVaddr = aXIPFileDetails.iROAddr; |
|
250 Elf32_Word textPaddr = aXIPFileDetails.iROAddr + addend; |
|
251 Elf32_Word textSize = aXIPFileDetails.iROSize; |
|
252 size_t textOffsetInRom = aXIPFileDetails.iROAddr - iRomDetails->iRomBaseLinearAddr; |
|
253 size_t textOffsetInElf = iE32RomImage.GetOffset() + textOffsetInRom; |
|
254 offset = InitROPHdr(thdr, textOffsetInElf, textVaddr, textPaddr, textSize); |
|
255 iElf32Header.AddProgramHdr(); |
|
256 iElfPHdrList.push_back(thdr); |
|
257 |
|
258 if (iRomDetails->iTrace){ |
|
259 cout << " " << aXIPFileDetails.iE32File << "\n"; |
|
260 cout.fill(' '); |
|
261 cout << left << " .text\n"; |
|
262 cout.fill('0'); |
|
263 cout << " paddr = 0x" << right << setw(8) << textPaddr << " vaddr = 0x" << right << setw(8)<< textVaddr |
|
264 << " offset = 0x" << right << setw(8) << textOffsetInElf |
|
265 << " size = 0x" << setw(8) << textSize << "\n" << flush; |
|
266 } |
|
267 |
|
268 if (aXIPFileDetails.iRWSize > 0){ |
|
269 ElfPHdr dhdr; |
|
270 Elf32_Word dataVaddr = aXIPFileDetails.iRWAddr; |
|
271 Elf32_Word dataPaddr = aXIPFileDetails.iROMDataAddr + addend; |
|
272 Elf32_Word fsize = aXIPFileDetails.iRWSize; |
|
273 Elf32_Word msize = aXIPFileDetails.iBSSDataSize; |
|
274 size_t dataOffsetInRom = aXIPFileDetails.iROMDataAddr - iRomDetails->iRomBaseLinearAddr; |
|
275 size_t dataOffsetInElf = iE32RomImage.GetOffset() + dataOffsetInRom; |
|
276 offset = InitRWPHdr(dhdr, dataOffsetInElf, dataVaddr, dataPaddr, fsize, msize); |
|
277 iElf32Header.AddProgramHdr(); |
|
278 iElfPHdrList.push_back(dhdr); |
|
279 |
|
280 if (iRomDetails->iTrace){ |
|
281 cout.fill(' '); |
|
282 cout << left << " .data\n"; |
|
283 cout.fill('0'); |
|
284 cout << " paddr = 0x" << right << setw(8) << dataPaddr << " vaddr = 0x" << right << setw(8)<< dataVaddr |
|
285 << " offset = 0x" << right << setw(8)<< dataOffsetInElf |
|
286 << " size = 0x" << right << setw(8) << fsize << "\n" << flush; |
|
287 } |
|
288 |
|
289 } |
|
290 return offset; |
|
291 } |
|
292 |
|
293 // This adds a header for the remainder of the ROM image after the last XIP file |
|
294 size_t ElfRom::AddFinalHeader(size_t offset){ |
|
295 ElfPHdr & lastHdr = iElfPHdrList.back(); |
|
296 Elf32_Word startAddr = lastHdr.GetPhdrPaddr() + lastHdr.GetPhdrFilesz(); |
|
297 ElfPHdr e32hdr; |
|
298 Elf32_Word e32hdrVaddr = startAddr; |
|
299 Elf32_Word e32hdrPaddr = startAddr; |
|
300 Elf32_Word e32hdrSize = iE32RomImage.Size() - offset + iE32RomImage.GetOffset(); |
|
301 |
|
302 offset = InitE32HdrPHdr(e32hdr, offset, e32hdrVaddr, e32hdrPaddr, e32hdrSize); |
|
303 |
|
304 iElf32Header.AddProgramHdr(); |
|
305 iElfPHdrList.push_back(e32hdr); |
|
306 |
|
307 if (iRomDetails->iTrace){ |
|
308 cout << "\nAdded final PHdr\n" << " offset 0x" << hex << right << setw(8) << offset |
|
309 << " size = 0x" << setw(8) << e32hdrSize << "\n"; |
|
310 } |
|
311 return offset; |
|
312 } |
|
313 |
|
314 void ElfRom::SetupAuxilarySections(){ |
|
315 SetupLogFile(); |
|
316 } |
|
317 |
|
318 void ElfRom::SetupLogFile(){ |
|
319 if (!iRomDetails->iLogFile.size()) return; |
|
320 InputFile * aLogFile = new InputFile(iRomDetails->iLogFile); |
|
321 ElfSectionFileData * aLogFileData = new ElfSectionFileData(aLogFile); |
|
322 Elf32_Shdr shdr; |
|
323 shdr.sh_name = 0; // for now. |
|
324 shdr.sh_offset = 0; // for now |
|
325 shdr.sh_info = 0; |
|
326 shdr.sh_link = SHN_UNDEF; |
|
327 shdr.sh_addr = 0; |
|
328 shdr.sh_addralign = 0; |
|
329 shdr.sh_type = SHT_PROGBITS; |
|
330 shdr.sh_size = 0; // for now. |
|
331 shdr.sh_flags = 0; |
|
332 shdr.sh_entsize = 0; |
|
333 |
|
334 ElfSection aLogFileSection(aLogFileData, "ROMLogFile", shdr); |
|
335 iElfSectionManager.AddSection(aLogFileSection); |
|
336 |
|
337 } |
|
338 |
|
339 void ElfRom::SetupELFRomData() { |
|
340 SetupProgramHeaderTable(); |
|
341 SetupAuxilarySections(); |
|
342 if (!iRomDetails->iStrip){ |
|
343 SetupSectionHeaderTable(); |
|
344 SetupSymbolTable(); |
|
345 if (!iRomDetails->iNoDwarf){ |
|
346 SetupDwarfSections(); |
|
347 } |
|
348 } |
|
349 } |
|
350 |
|
351 void ElfRom::SetupSectionHeaderTable(){ |
|
352 RomDetails::XIPFileList::iterator aXIPFile = iRomDetails->iXIPFiles.begin(); |
|
353 RomDetails::XIPFileList::iterator end = iRomDetails->iXIPFiles.end(); |
|
354 |
|
355 if (iRomDetails->iTrace && aXIPFile != end){ |
|
356 cout << "\nAdding Section headers from associated ELF files\n"; |
|
357 } |
|
358 |
|
359 while (aXIPFile != end) { |
|
360 SetupSectionHeaders(*aXIPFile); |
|
361 aXIPFile++; |
|
362 } |
|
363 } |
|
364 |
|
365 void ElfRom::SetupSectionHeaders(XIPFileDetails & aXIPFileDetails) { |
|
366 // Open ELF file |
|
367 PathName aPath = aXIPFileDetails.iElfFile; |
|
368 |
|
369 if (aPath.size() == 0) return; |
|
370 |
|
371 int fd; |
|
372 Elf * e; |
|
373 size_t shstrndx; |
|
374 bool hasSectionStringTable = true; |
|
375 |
|
376 |
|
377 if ((fd = open(aPath.c_str(), O_RDONLY|O_BINARY, 0)) < 0){ |
|
378 warnx(EX_NOINPUT, "open \"%s\" failed\n", aPath.c_str()); |
|
379 goto finish; |
|
380 } |
|
381 if ((e = elf_begin(fd, ELF_C_READ , NULL)) == NULL) |
|
382 errx(EX_SOFTWARE, "elf_begin() failed: %s.\n", elf_errmsg(-1)); |
|
383 if (elf_kind(e) != ELF_K_ELF) |
|
384 errx(EX_SOFTWARE, "file not of kind ELF_K_ELF: %s.\n", aPath.c_str()); |
|
385 if (elf_getshstrndx(e, &shstrndx) == 0) { |
|
386 hasSectionStringTable = false; |
|
387 warnx(EX_SOFTWARE, "getshstrndx() failed for \"%s\"\n", aPath.c_str()); |
|
388 } |
|
389 if (hasSectionStringTable){ |
|
390 SetUpSegmentInfo(aXIPFileDetails, e); |
|
391 SetupSectionHeaders(aXIPFileDetails, e, shstrndx); |
|
392 } |
|
393 |
|
394 elf_end(e); |
|
395 close(fd); |
|
396 finish: |
|
397 return; |
|
398 } |
|
399 |
|
400 void ElfRom::SetupSectionHeaders(XIPFileDetails & aXIPFileDetails, Elf * e, size_t shstrndx){ |
|
401 // Iterate through sections looking for the ones we're after. Namely: |
|
402 // text, data, bss/zi, symtab, strtable, and .debug* |
|
403 Elf_Scn * scn = NULL; |
|
404 Elf32_Shdr * shdr; |
|
405 SectionNumberMap aSectionNumberMap; |
|
406 SectionVaddrAddendMap aSectionVaddrAddendMap; |
|
407 |
|
408 String aPath(aXIPFileDetails.iElfFile); |
|
409 |
|
410 const char * debugName = ".debug"; |
|
411 const size_t debugNameLength = strlen(debugName); |
|
412 const char * staticStrTab = ".strtab"; |
|
413 |
|
414 if (iRomDetails->iTrace){ |
|
415 cout << " " << aXIPFileDetails.iElfFile << "\n"; |
|
416 } |
|
417 |
|
418 while ((scn = elf_nextscn(e, scn)) != NULL) { |
|
419 |
|
420 if ((shdr = elf32_getshdr(scn)) == NULL) |
|
421 errx(EX_SOFTWARE, "getshdr() failed: %s.\n", elf_errmsg(-1)); |
|
422 |
|
423 size_t aOldNdx = elf_ndxscn(scn); |
|
424 char * name = elf_strptr(e, shstrndx, shdr->sh_name); |
|
425 VirtualAddr sectionAddr = shdr->sh_addr; |
|
426 |
|
427 switch (shdr->sh_type) { |
|
428 case SHT_NOBITS: |
|
429 // Check for BSS or ZI |
|
430 if ((shdr->sh_flags & SHF_WRITE) && (shdr->sh_flags & SHF_ALLOC)) { |
|
431 // set up section number mapping |
|
432 size_t aNew = AddBssSectionHeader(aXIPFileDetails, shdr, name); |
|
433 aSectionNumberMap.push_back(SectionNumberMapping(aOldNdx, aNew)); |
|
434 // set up address adjustment for relocation of e.g. symbols |
|
435 int addend = aXIPFileDetails.iBSSAddr - sectionAddr; |
|
436 aSectionVaddrAddendMap.push_back(SectionVaddrAddendMapping(aOldNdx, addend)); |
|
437 } |
|
438 break; |
|
439 #define ARM_EXIDX (SHT_LOPROC + 1) |
|
440 case ARM_EXIDX: |
|
441 case SHT_PROGBITS: |
|
442 // text/ro or data/rw will have SHF_ALLOC set |
|
443 if (shdr->sh_flags & SHF_ALLOC) { |
|
444 size_t aNew = 0; |
|
445 int addend = 0; |
|
446 if (shdr->sh_flags & SHF_WRITE) { |
|
447 aNew = AddRwSectionHeader(aXIPFileDetails, shdr, name); |
|
448 addend = aXIPFileDetails.iRWAddr - sectionAddr; |
|
449 } else { |
|
450 aNew = AddRoSectionHeader(aXIPFileDetails, shdr, name); |
|
451 addend = aXIPFileDetails.iROAddr - sectionAddr; |
|
452 } |
|
453 // set up section number mapping |
|
454 aSectionNumberMap.push_back(SectionNumberMapping(aOldNdx, aNew)); |
|
455 // set up address adjustment for relocation of e.g. symbols |
|
456 aSectionVaddrAddendMap.push_back(SectionVaddrAddendMapping(aOldNdx, addend)); |
|
457 } else if (!iRomDetails->iNoDwarf && !strncmp(debugName, name, debugNameLength)) { |
|
458 iDwarfFound = true; |
|
459 iDwarfManager.AddSection(aXIPFileDetails, name, shdr); |
|
460 } |
|
461 break; |
|
462 case SHT_SYMTAB: |
|
463 iElfSymbolTableManager.AddSymbolTable(aPath, shdr->sh_offset, shdr->sh_size, shdr->sh_info); |
|
464 break; |
|
465 case SHT_STRTAB: |
|
466 if (!strcmp(staticStrTab, name)) |
|
467 iElfSymbolTableManager.AddStringTable(aPath, shdr->sh_offset, shdr->sh_size); |
|
468 break; |
|
469 } |
|
470 } |
|
471 iElfSymbolTableManager.Finalize(aSectionNumberMap, aSectionVaddrAddendMap); |
|
472 } |
|
473 |
|
474 size_t ElfRom::AddRoSectionHeader(XIPFileDetails & aXIPFileDetails, Elf32_Shdr * aShdr, char * aName){ |
|
475 size_t delta = aShdr->sh_addr - aXIPFileDetails.iElfTextBase; |
|
476 VirtualAddr vaddr = aXIPFileDetails.iROAddr + delta; |
|
477 size_t offsetInRom = vaddr - iRomDetails->iRomBaseLinearAddr; |
|
478 size_t offsetInElf = iE32RomImage.GetOffset() + offsetInRom; |
|
479 aShdr->sh_addr = vaddr; |
|
480 return AddROMSectionHeader(aXIPFileDetails, aShdr, aName, offsetInElf ); |
|
481 } |
|
482 |
|
483 size_t ElfRom::AddRwSectionHeader(XIPFileDetails & aXIPFileDetails, Elf32_Shdr * aShdr, char * aName){ |
|
484 size_t delta = aShdr->sh_addr - aXIPFileDetails.iElfDataBase; |
|
485 VirtualAddr vaddr = aXIPFileDetails.iROMDataAddr + delta; |
|
486 size_t offsetInRom = vaddr - iRomDetails->iRomBaseLinearAddr; |
|
487 size_t offsetInElf = iE32RomImage.GetOffset() + offsetInRom; |
|
488 aShdr->sh_addr = aXIPFileDetails.iRWAddr; |
|
489 return AddROMSectionHeader(aXIPFileDetails, aShdr, aName, offsetInElf); |
|
490 } |
|
491 |
|
492 size_t ElfRom::AddBssSectionHeader(XIPFileDetails & aXIPFileDetails, Elf32_Shdr * aShdr, char * aName){ |
|
493 size_t delta = aShdr->sh_addr - aXIPFileDetails.iElfDataBase; |
|
494 VirtualAddr vaddr = aXIPFileDetails.iROMDataAddr + delta; |
|
495 size_t offsetInRom = vaddr - iRomDetails->iRomBaseLinearAddr; |
|
496 size_t offsetInElf = iE32RomImage.GetOffset() + offsetInRom; |
|
497 aShdr->sh_addr = aXIPFileDetails.iBSSAddr; |
|
498 return AddROMSectionHeader(aXIPFileDetails, aShdr, aName, offsetInElf); |
|
499 } |
|
500 |
|
501 size_t ElfRom::AddROMSectionHeader(XIPFileDetails & aXIPFileDetails, Elf32_Shdr * aShdr, char * aName, size_t aOffset){ |
|
502 ElfSectionData * romData = aOffset ? |
|
503 (ElfSectionData *)new ElfSectionRomData(aOffset, aShdr->sh_size) |
|
504 : (ElfSectionData *)new ElfSectionNoData(); |
|
505 ElfSection aSection(romData, aName, *aShdr); |
|
506 iElfSectionManager.AddSection(aSection); |
|
507 |
|
508 if (iRomDetails->iTrace){ |
|
509 cout.fill(' '); |
|
510 cout << " " << left << setw(22) << aName << "\n"; |
|
511 cout.fill('0'); |
|
512 cout << " vaddr = 0x" << right << hex << setw(8) << aShdr->sh_addr << " offset = 0x" |
|
513 << right << hex << setw(8) << aOffset |
|
514 << " size = 0x" << right << hex << setw(8) << aShdr->sh_size << "\n"; |
|
515 } |
|
516 return aSection.GetIndex(); |
|
517 } |
|
518 |
|
519 void ElfRom::SetUpSegmentInfo(XIPFileDetails & aXIPFileDetails, Elf * e){ |
|
520 Elf32_Ehdr * ehdr = elf32_getehdr(e); |
|
521 if (ehdr == NULL) |
|
522 errx(EX_SOFTWARE, "elf32_getehdr() failed: %s.", elf_errmsg(-1)); |
|
523 size_t n = ehdr->e_phnum; |
|
524 Elf32_Phdr * phdr = elf32_getphdr(e); |
|
525 if (phdr == NULL) |
|
526 errx(EX_SOFTWARE, "elf32_getphdr() failed: %s.", elf_errmsg(-1)); |
|
527 |
|
528 for (size_t i = 0; i < n; i++) { |
|
529 if (phdr[i].p_flags & PF_X){ |
|
530 VirtualAddr segmentAddr = phdr[i].p_vaddr; |
|
531 aXIPFileDetails.iElfTextBase = segmentAddr; |
|
532 aXIPFileDetails.iElfTextLimit = segmentAddr + phdr[i].p_memsz; |
|
533 |
|
534 } else if (phdr[i].p_flags & PF_W){ |
|
535 aXIPFileDetails.iElfDataBase = phdr[i].p_vaddr; |
|
536 } |
|
537 } |
|
538 } |
|
539 |
|
540 void ElfRom::SetupSymbolTable(){ |
|
541 iElfSymbolTableManager.AddSymbolTable(); |
|
542 if (iRomDetails->iTrace){ |
|
543 cout << "\nAdded section headers for combined symbol table and symbol string table\n"; |
|
544 } |
|
545 } |
|
546 |
|
547 void ElfRom::SetupDwarfSections(){ |
|
548 if (iRomDetails->iTrace && iDwarfFound){ |
|
549 cout << "\nSetting up Dwarf Sections\n"; |
|
550 } else if (iRomDetails->iTrace && !iDwarfFound && !iRomDetails->iNoDwarf){ |
|
551 cout << "\nWarning: No Dwarf information found\n"; |
|
552 return; |
|
553 } |
|
554 iDwarfManager.SetupSections(); |
|
555 } |
|
556 |
|
557 void ElfRom::AddData() { |
|
558 iElfSectionManager.AddData(); |
|
559 iElf32Header.SetSectionHdrOffset(iElfSectionManager.GetOffset()); |
|
560 } |
|
561 |
|
562 void ElfRom::Dump(){ |
|
563 iOutputFile.Dump(); |
|
564 if (iRomDetails->iTrace){ |
|
565 cout << "\nWrote " << iRomDetails->iElfRomFile << " " << dec << iOutputFile.Size() << " bytes\n"; |
|
566 } |
|
567 } |