]>
Commit | Line | Data |
---|---|---|
fd67aa11 | 1 | /* Copyright (C) 2021-2024 Free Software Foundation, Inc. |
bb368aad VM |
2 | Contributed by Oracle. |
3 | ||
4 | This file is part of GNU Binutils. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 3, or (at your option) | |
9 | any later version. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
18 | Foundation, 51 Franklin Street - Fifth Floor, Boston, | |
19 | MA 02110-1301, USA. */ | |
20 | ||
21 | #include "config.h" | |
22 | #include <unistd.h> | |
23 | ||
24 | #include "util.h" | |
25 | #include "bfd.h" | |
26 | #include "elf-bfd.h" | |
27 | #include "Elf.h" | |
28 | #include "Map.h" | |
29 | #include "StringBuilder.h" | |
30 | #include "DbeFile.h" | |
31 | ||
32 | typedef uint32_t Elf32_Word; | |
33 | typedef uint32_t Elf64_Word; | |
34 | typedef uint32_t Elf32_Addr; | |
35 | typedef uint64_t Elf64_Addr; | |
36 | typedef uint64_t Elf64_Xword; | |
37 | typedef int32_t Elf32_Sword; | |
38 | typedef int64_t Elf64_Sxword; | |
39 | typedef uint16_t Elf32_Half; | |
40 | typedef uint16_t Elf64_Half; | |
41 | ||
42 | // Ancillary entry | |
43 | typedef struct | |
44 | { | |
45 | Elf32_Word a_tag; /* how to interpret value */ | |
46 | union | |
47 | { | |
48 | Elf32_Word a_val; | |
49 | Elf32_Addr a_ptr; | |
50 | } a_un; | |
51 | } Elf32_Ancillary; | |
52 | ||
53 | struct S_Elf64_Ancillary | |
54 | { | |
55 | Elf64_Xword a_tag; /* how to interpret value */ | |
56 | union | |
57 | { | |
58 | Elf64_Xword a_val; | |
59 | Elf64_Addr a_ptr; | |
60 | } a_un; | |
61 | }; | |
62 | ||
63 | /* Dynamic section entry. */ | |
64 | typedef struct | |
65 | { | |
66 | Elf32_Sword d_tag; /* Dynamic entry type */ | |
67 | ||
68 | union | |
69 | { | |
70 | Elf32_Word d_val; /* Integer value */ | |
71 | Elf32_Addr d_ptr; /* Address value */ | |
72 | } d_un; | |
73 | } Elf32_Dyn; | |
74 | ||
75 | struct S_Elf64_Dyn | |
76 | { | |
77 | Elf64_Sxword d_tag; /* Dynamic entry type */ | |
78 | ||
79 | union | |
80 | { | |
81 | Elf64_Xword d_val; /* Integer value */ | |
82 | Elf64_Addr d_ptr; /* Address value */ | |
83 | } d_un; | |
84 | }; | |
85 | ||
86 | ||
87 | // Symbol table | |
88 | typedef struct | |
89 | { | |
90 | Elf32_Word st_name; | |
91 | Elf32_Addr st_value; | |
92 | Elf32_Word st_size; | |
93 | unsigned char st_info; /* bind, type: ELF_32_ST_... */ | |
94 | unsigned char st_other; | |
95 | Elf32_Half st_shndx; /* SHN_... */ | |
96 | } Elf32_Sym; | |
97 | ||
98 | typedef struct | |
99 | { | |
100 | Elf64_Word st_name; | |
101 | unsigned char st_info; /* bind, type: ELF_64_ST_... */ | |
102 | unsigned char st_other; | |
103 | Elf64_Half st_shndx; /* SHN_... */ | |
104 | Elf64_Addr st_value; | |
105 | Elf64_Xword st_size; | |
106 | } Elf64_Sym; | |
107 | ||
108 | ||
109 | // Relocation | |
110 | typedef struct | |
111 | { | |
112 | Elf32_Addr r_offset; | |
113 | Elf32_Word r_info; /* sym, type: ELF32_R_... */ | |
114 | } Elf32_Rel; | |
115 | ||
116 | typedef struct | |
117 | { | |
118 | Elf32_Addr r_offset; | |
119 | Elf32_Word r_info; /* sym, type: ELF32_R_... */ | |
120 | Elf32_Sword r_addend; | |
121 | } Elf32_Rela; | |
122 | ||
123 | typedef struct | |
124 | { | |
125 | Elf64_Addr r_offset; | |
126 | Elf64_Xword r_info; /* sym, type: ELF64_R_... */ | |
127 | } Elf64_Rel; | |
128 | ||
129 | typedef struct | |
130 | { | |
131 | Elf64_Addr r_offset; | |
132 | Elf64_Xword r_info; /* sym, type: ELF64_R_... */ | |
133 | Elf64_Sxword r_addend; | |
134 | } Elf64_Rela; | |
135 | ||
136 | int Elf::bfd_status = -1; | |
137 | ||
138 | void | |
139 | Elf::elf_init () | |
140 | { | |
141 | if (bfd_status == -1) | |
142 | bfd_status = bfd_init (); | |
143 | } | |
144 | ||
145 | Elf::Elf (char *filename) : DbeMessages (), Data_window (filename) | |
146 | { | |
147 | ehdrp = NULL; | |
148 | data = NULL; | |
149 | ancillary_files = NULL; | |
150 | elfSymbols = NULL; | |
151 | gnu_debug_file = NULL; | |
152 | dbeFile = NULL; | |
153 | abfd = NULL; | |
7434de7e VM |
154 | bfd_symcnt = -1; |
155 | bfd_dynsymcnt = -1; | |
156 | bfd_synthcnt = -1; | |
157 | bfd_sym = NULL; | |
158 | bfd_dynsym = NULL; | |
159 | bfd_synthsym = NULL; | |
160 | synthsym = NULL; | |
161 | ||
bb368aad VM |
162 | if (bfd_status != BFD_INIT_MAGIC) |
163 | { | |
164 | status = ELF_ERR_CANT_OPEN_FILE; | |
165 | return; | |
166 | } | |
167 | abfd = bfd_openr (filename, NULL); | |
168 | if (abfd == NULL) | |
169 | { | |
170 | status = ELF_ERR_CANT_OPEN_FILE; | |
171 | return; | |
172 | } | |
7434de7e | 173 | abfd->flags |= BFD_DECOMPRESS; |
bb368aad VM |
174 | if (!bfd_check_format (abfd, bfd_object)) |
175 | { | |
176 | bfd_close (abfd); | |
177 | abfd = NULL; | |
178 | status = ELF_ERR_CANT_OPEN_FILE; | |
179 | return; | |
180 | } | |
181 | ehdrp = elf_getehdr (); | |
182 | if (ehdrp == NULL) | |
183 | { | |
184 | bfd_close (abfd); | |
185 | abfd = NULL; | |
186 | status = ELF_ERR_BAD_ELF_FORMAT; | |
187 | return; | |
188 | } | |
189 | elf_class = ehdrp->e_ident[EI_CLASS]; | |
190 | elf_datatype = ehdrp->e_ident[EI_DATA]; | |
191 | ||
192 | if (not_opened ()) | |
193 | { | |
194 | status = ELF_ERR_CANT_OPEN_FILE; | |
195 | return; | |
196 | } | |
197 | status = ELF_ERR_NONE; | |
198 | ||
199 | #if ARCH(SPARC) | |
200 | need_swap_endian = is_Intel (); | |
201 | #else | |
202 | need_swap_endian = !is_Intel (); | |
203 | #endif | |
204 | ||
205 | analyzerInfo = 0; | |
206 | SUNW_ldynsym = 0; | |
207 | gnuLink = 0; | |
208 | stab = 0; | |
209 | stabStr = 0; | |
210 | stabIndex = 0; | |
211 | stabIndexStr = 0; | |
212 | stabExcl = 0; | |
213 | stabExclStr = 0; | |
214 | symtab = 0; | |
215 | dynsym = 0; | |
216 | info = 0; | |
217 | plt = 0; | |
218 | dwarf = false; | |
219 | ||
220 | for (unsigned int sec = 1; sec < elf_getehdr ()->e_shnum; sec++) | |
221 | { | |
222 | char *name = get_sec_name (sec); | |
223 | if (name == NULL) | |
224 | continue; | |
225 | if (streq (name, NTXT (".stab"))) | |
226 | stab = sec; | |
227 | else if (streq (name, NTXT (".stabstr"))) | |
228 | stabStr = sec; | |
229 | else if (streq (name, NTXT (".stab.index"))) | |
230 | stabIndex = sec; | |
231 | else if (streq (name, NTXT (".stab.indexstr"))) | |
232 | stabIndexStr = sec; | |
233 | else if (streq (name, NTXT (".stab.excl"))) | |
234 | stabExcl = sec; | |
235 | else if (streq (name, NTXT (".stab.exclstr"))) | |
236 | stabExclStr = sec; | |
237 | else if (streq (name, NTXT (".gnu_debuglink"))) | |
238 | gnuLink = sec; | |
239 | else if (streq (name, NTXT (".__analyzer_info"))) | |
240 | analyzerInfo = sec; | |
241 | else if (streq (name, NTXT (".info"))) | |
242 | info = true; | |
243 | else if (streq (name, NTXT (".plt"))) | |
244 | plt = sec; | |
245 | else if (streq (name, NTXT (".SUNW_ldynsym"))) | |
246 | SUNW_ldynsym = sec; | |
247 | else if (streq (name, NTXT (".dynsym"))) | |
248 | dynsym = sec; | |
249 | else if (streq (name, NTXT (".symtab"))) | |
250 | symtab = sec; | |
251 | else if (strncmp (name, NTXT (".debug"), 6) == 0) | |
252 | dwarf = true; | |
253 | } | |
254 | if (fd != -1) | |
255 | { | |
256 | close (fd); | |
257 | fd = -1; | |
258 | } | |
259 | } | |
260 | ||
261 | Elf::~Elf () | |
262 | { | |
263 | if (data) | |
264 | { | |
265 | for (int i = 0; i < (int) ehdrp->e_shnum; i++) | |
266 | { | |
267 | Elf_Data *p = data[i]; | |
268 | if (p && !mmap_on_file && (p->d_flags & SHF_SUNW_ABSENT) == 0) | |
269 | free (p->d_buf); | |
270 | delete p; | |
271 | } | |
272 | free (data); | |
273 | } | |
274 | if (ancillary_files) | |
275 | { | |
276 | ancillary_files->destroy (); | |
277 | delete ancillary_files; | |
278 | } | |
279 | delete elfSymbols; | |
280 | delete gnu_debug_file; | |
281 | delete dbeFile; | |
7434de7e VM |
282 | delete synthsym; |
283 | free (bfd_sym); | |
284 | free (bfd_dynsym); | |
285 | free (bfd_synthsym); | |
bb368aad VM |
286 | if (abfd) |
287 | bfd_close (abfd); | |
288 | } | |
289 | ||
290 | Elf_Internal_Ehdr * | |
291 | Elf::elf_getehdr () | |
292 | { | |
293 | if (ehdrp == NULL && abfd) | |
294 | ehdrp = elf_elfheader (abfd); | |
295 | return ehdrp; | |
296 | } | |
297 | ||
298 | Elf_Internal_Phdr * | |
299 | Elf::get_phdr (unsigned int ndx) | |
300 | { | |
301 | if (ehdrp == NULL || ndx >= ehdrp->e_phnum) | |
302 | return NULL; | |
303 | return &(elf_tdata (abfd)->phdr[ndx]); | |
304 | } | |
305 | ||
306 | Elf_Internal_Shdr * | |
307 | Elf::get_shdr (unsigned int ndx) | |
308 | { | |
309 | if (ehdrp == NULL || ndx >= ehdrp->e_shnum) | |
310 | return NULL; | |
311 | return elf_elfsections (abfd)[ndx]; | |
312 | } | |
313 | ||
314 | Elf64_Dyn * | |
315 | Elf::elf_getdyn (Elf_Internal_Phdr *phdr, unsigned int ndx, Elf64_Dyn *pdyn) | |
316 | { | |
317 | if (elf_getclass () == ELFCLASS32) | |
318 | { | |
319 | if (ndx * sizeof (Elf32_Dyn) >= phdr->p_filesz) | |
320 | return NULL; | |
321 | Elf32_Dyn *hdr = (Elf32_Dyn*) bind (phdr->p_offset + ndx * sizeof (Elf32_Dyn), | |
322 | sizeof (Elf32_Dyn)); | |
323 | if (hdr == NULL) | |
324 | return NULL; | |
325 | pdyn->d_tag = decode (hdr->d_tag); | |
326 | pdyn->d_un.d_val = decode (hdr->d_un.d_val); | |
327 | } | |
328 | else | |
329 | { | |
330 | if (ndx * sizeof (Elf64_Dyn) >= phdr->p_filesz) | |
331 | return NULL; | |
332 | Elf64_Dyn *hdr = (Elf64_Dyn*) bind (phdr->p_offset + ndx * sizeof (Elf64_Dyn), | |
333 | sizeof (Elf64_Dyn)); | |
334 | if (hdr == NULL) | |
335 | return NULL; | |
336 | pdyn->d_tag = decode (hdr->d_tag); | |
337 | pdyn->d_un.d_val = decode (hdr->d_un.d_val); | |
338 | } | |
339 | return pdyn; | |
340 | } | |
341 | ||
342 | unsigned | |
343 | Elf::elf_version (unsigned ver) | |
344 | { | |
345 | // We compile locally, no need to check the version | |
346 | return ver; | |
347 | } | |
348 | ||
349 | Elf * | |
350 | Elf::elf_begin (char *fname, Elf_status *stp) | |
351 | { | |
352 | if (fname == NULL) | |
353 | { | |
354 | if (stp) | |
355 | *stp = ELF_ERR_CANT_OPEN_FILE; | |
356 | return NULL; | |
357 | } | |
358 | Elf *elf = new Elf (fname); | |
359 | if (stp) | |
360 | *stp = elf->status; | |
361 | if (elf->status != ELF_ERR_NONE) | |
362 | { | |
363 | delete elf; | |
364 | return NULL; | |
365 | } | |
366 | #if DEBUG | |
367 | if (DUMP_ELF_SEC) | |
368 | { | |
369 | char *str = elf->dump (); | |
370 | fprintf (stderr, NTXT ("%s\n\n"), str); | |
371 | free (str); | |
372 | } | |
373 | #endif /* DEBUG */ | |
374 | return elf; | |
375 | } | |
376 | ||
377 | unsigned int | |
378 | Elf::elf_get_sec_num (const char *name) | |
379 | { | |
380 | if (name == NULL || ehdrp == NULL) | |
381 | return 0; | |
382 | for (unsigned int sec = 1; sec < ehdrp->e_shnum; sec++) | |
383 | { | |
384 | Elf_Internal_Shdr *shdr = get_shdr (sec); | |
385 | if (shdr == NULL) | |
386 | continue; | |
387 | char *sname = elf_strptr (ehdrp->e_shstrndx, shdr->sh_name); | |
388 | if (sname != NULL && strcmp (name, sname) == 0) | |
389 | return sec; | |
390 | } | |
391 | return 0; | |
392 | } | |
393 | ||
394 | char * | |
395 | Elf::get_sec_name (unsigned int sec) | |
396 | { | |
397 | Elf_Internal_Shdr *shdr = get_shdr (sec); | |
398 | if (ehdrp == NULL || shdr == NULL) | |
399 | return NULL; | |
400 | return elf_strptr (ehdrp->e_shstrndx, shdr->sh_name); | |
401 | } | |
402 | ||
403 | Elf_Data * | |
404 | Elf::elf_getdata (unsigned int sec) | |
405 | { | |
406 | if (data == NULL) | |
407 | { | |
408 | data = (Elf_Data **) malloc (ehdrp->e_shnum * sizeof (Elf_Data *)); | |
409 | for (int i = 0; i < (int) ehdrp->e_shnum; i++) | |
410 | data[i] = NULL; | |
411 | } | |
412 | Elf_Data *edta = data[sec]; | |
413 | if (edta == NULL) | |
414 | { | |
415 | Elf_Internal_Shdr *shdr = get_shdr (sec); | |
416 | if (shdr == NULL) | |
417 | return NULL; | |
418 | edta = new Elf_Data; | |
419 | data[sec] = edta; | |
420 | if ((shdr->sh_flags & SHF_SUNW_ABSENT) != 0) | |
421 | { | |
422 | char *sname = get_sec_name (sec); | |
423 | for (int i = 0, sz = VecSize(ancillary_files); i < sz; i++) | |
424 | { | |
425 | Elf *ancElf = ancillary_files->fetch (i); | |
426 | int secNum = sec; | |
427 | if (dbe_strcmp (sname, ancElf->get_sec_name (sec)) != 0) | |
428 | { | |
429 | append_msg (CMSG_WARN, | |
430 | "Warning: the section #%d (%s) is mismatch in ancillary file '%s')\n", | |
431 | sec, STR (sname), STR (ancElf->fname)); | |
432 | secNum = ancElf->elf_get_sec_num (sname); | |
433 | } | |
434 | if (secNum > 0) | |
435 | { | |
436 | Elf_Data *ed = ancElf->elf_getdata (secNum); | |
437 | if (ed && ed->d_buf) | |
438 | { | |
439 | *edta = *ed; | |
440 | edta->d_flags |= SHF_SUNW_ABSENT; | |
441 | return edta; | |
442 | } | |
443 | } | |
444 | } | |
445 | } | |
446 | edta->d_buf = get_data (shdr->sh_offset, (size_t) shdr->sh_size, NULL); | |
447 | edta->d_flags = shdr->sh_flags; | |
448 | edta->d_size = ((edta->d_buf == NULL) || (shdr->sh_type == SHT_NOBITS)) ? 0 : shdr->sh_size; | |
449 | edta->d_off = shdr->sh_offset; | |
450 | edta->d_align = shdr->sh_addralign; | |
451 | } | |
452 | return edta; | |
453 | } | |
454 | ||
455 | int64_t | |
456 | Elf::elf_checksum () | |
457 | { | |
458 | if (ehdrp == NULL) | |
459 | return 0; | |
460 | int64_t chk = 0; | |
461 | for (unsigned int ndx = 0; ndx < ehdrp->e_phnum; ndx++) | |
462 | { | |
463 | Elf_Internal_Phdr *phdr = get_phdr (ndx); | |
464 | if (phdr == NULL) | |
465 | continue; | |
466 | if (phdr->p_type == PT_DYNAMIC) | |
467 | { | |
468 | Elf64_Dyn edyn; | |
469 | for (unsigned int i = 0; elf_getdyn (phdr, i, &edyn) != NULL; i++) | |
470 | { | |
471 | if (!edyn.d_tag) | |
472 | break; | |
473 | if (edyn.d_tag == DT_CHECKSUM) | |
474 | { | |
475 | chk = edyn.d_un.d_val; | |
476 | break; | |
477 | } | |
478 | } | |
479 | } | |
480 | } | |
481 | return normalize_checksum (chk); | |
482 | } | |
483 | ||
484 | uint64_t | |
485 | Elf::get_baseAddr () | |
486 | { | |
487 | uint64_t addr = 0; | |
488 | for (unsigned int pnum = 0; pnum < elf_getehdr ()->e_phnum; pnum++) | |
489 | { | |
490 | Elf_Internal_Phdr *phdr = get_phdr (pnum); | |
491 | if (phdr->p_type == PT_LOAD && phdr->p_flags == (PF_R | PF_X)) | |
492 | { | |
493 | if (addr == 0) | |
494 | addr = phdr->p_vaddr; | |
495 | else | |
496 | { | |
497 | addr = 0; | |
498 | break; | |
499 | } | |
500 | } | |
501 | } | |
502 | return addr; | |
503 | } | |
504 | ||
505 | char * | |
506 | Elf::elf_strptr (unsigned int sec, uint64_t off) | |
507 | { | |
508 | Elf_Data *edta = elf_getdata (sec); | |
509 | if (edta && edta->d_buf && edta->d_size > off) | |
510 | return ((char *) edta->d_buf) + off; | |
511 | return NULL; | |
512 | } | |
513 | ||
514 | Elf_Internal_Sym * | |
515 | Elf::elf_getsym (Elf_Data *edta, unsigned int ndx, Elf_Internal_Sym *dst) | |
516 | { | |
517 | if (dst == NULL || edta == NULL) | |
518 | return NULL; | |
519 | if (elf_getclass () == ELFCLASS32) | |
520 | { | |
521 | if (edta->d_size <= ndx * sizeof (Elf32_Sym)) | |
522 | return NULL; | |
523 | Elf32_Sym *hdr = (Elf32_Sym*) bind (edta->d_off + ndx * sizeof (Elf32_Sym), sizeof (Elf32_Sym)); | |
524 | if (hdr == NULL) | |
525 | return NULL; | |
526 | dst->st_name = decode (hdr->st_name); | |
527 | dst->st_value = decode (hdr->st_value); | |
528 | dst->st_size = decode (hdr->st_size); | |
529 | dst->st_info = ELF64_ST_INFO (ELF32_ST_BIND (decode (hdr->st_info)), | |
530 | ELF32_ST_TYPE (decode (hdr->st_info))); | |
531 | dst->st_other = decode (hdr->st_other); | |
532 | dst->st_shndx = decode (hdr->st_shndx); | |
533 | } | |
534 | else | |
535 | { | |
536 | if (edta->d_size <= ndx * sizeof (Elf64_Sym)) | |
537 | return NULL; | |
538 | Elf64_Sym *hdr = (Elf64_Sym*) bind (edta->d_off + ndx * sizeof (Elf64_Sym), | |
539 | sizeof (Elf64_Sym)); | |
540 | if (hdr == NULL) | |
541 | return NULL; | |
542 | dst->st_name = decode (hdr->st_name); | |
543 | dst->st_value = decode (hdr->st_value); | |
544 | dst->st_size = decode (hdr->st_size); | |
545 | dst->st_info = decode (hdr->st_info); | |
546 | dst->st_other = decode (hdr->st_other); | |
547 | dst->st_shndx = decode (hdr->st_shndx); | |
548 | } | |
549 | return dst; | |
550 | } | |
551 | ||
552 | Elf_Internal_Rela * | |
553 | Elf::elf_getrel (Elf_Data *edta, unsigned int ndx, Elf_Internal_Rela *dst) | |
554 | { | |
555 | if (dst == NULL || edta == NULL || edta->d_buf == NULL) | |
556 | return NULL; | |
557 | if (elf_getclass () == ELFCLASS32) | |
558 | { | |
559 | Elf32_Rel *rel = ((Elf32_Rel *) edta->d_buf) + ndx; | |
560 | dst->r_offset = decode (rel->r_offset); | |
561 | dst->r_info = ELF64_R_INFO (ELF32_R_SYM (decode (rel->r_info)), | |
562 | ELF32_R_TYPE (decode (rel->r_info))); | |
563 | } | |
564 | else | |
565 | { | |
566 | Elf64_Rel *rel = ((Elf64_Rel *) edta->d_buf) + ndx; | |
567 | dst->r_offset = decode (rel->r_offset); | |
568 | dst->r_info = decode (rel->r_info); | |
569 | } | |
570 | return dst; | |
571 | } | |
572 | ||
573 | Elf_Internal_Rela * | |
574 | Elf::elf_getrela (Elf_Data *edta, unsigned int ndx, Elf_Internal_Rela *dst) | |
575 | { | |
576 | if (dst == NULL || edta == NULL || edta->d_buf == NULL) | |
577 | return NULL; | |
578 | if (elf_getclass () == ELFCLASS32) | |
579 | { | |
580 | Elf32_Rela *rela = ((Elf32_Rela *) edta->d_buf) + ndx; | |
581 | dst->r_offset = decode (rela->r_offset); | |
582 | dst->r_addend = decode (rela->r_addend); | |
583 | dst->r_info = ELF64_R_INFO (ELF32_R_SYM (decode (rela->r_info)), | |
584 | ELF32_R_TYPE (decode (rela->r_info))); | |
585 | } | |
586 | else | |
587 | { | |
588 | Elf64_Rela *rela = ((Elf64_Rela *) edta->d_buf) + ndx; | |
589 | dst->r_offset = decode (rela->r_offset); | |
590 | dst->r_addend = decode (rela->r_addend); | |
591 | dst->r_info = decode (rela->r_info); | |
592 | } | |
593 | return dst; | |
594 | } | |
595 | ||
596 | Elf64_Ancillary * | |
597 | Elf::elf_getancillary (Elf_Data *edta, unsigned int ndx, Elf64_Ancillary *dst) | |
598 | { | |
599 | if (dst == NULL || edta == NULL || edta->d_buf == NULL) | |
600 | return NULL; | |
601 | if (elf_getclass () == ELFCLASS32) | |
602 | { | |
603 | Elf32_Ancillary *p = ((Elf32_Ancillary *) edta->d_buf) + ndx; | |
604 | dst->a_tag = decode (p->a_tag); | |
605 | dst->a_un.a_val = decode (p->a_un.a_val); | |
606 | } | |
607 | else | |
608 | { | |
609 | Elf64_Ancillary *p = ((Elf64_Ancillary *) edta->d_buf) + ndx; | |
610 | dst->a_tag = decode (p->a_tag); | |
611 | dst->a_un.a_val = decode (p->a_un.a_val); | |
612 | } | |
613 | return dst; | |
614 | } | |
615 | ||
616 | Elf * | |
617 | Elf::get_related_file (const char *lo_name, const char *nm) | |
618 | { | |
619 | DbeFile *df; | |
620 | if (*nm == '/') | |
621 | { | |
622 | df = new DbeFile (nm); | |
623 | df->filetype |= (DbeFile::F_FILE | DbeFile::F_DEBUG_FILE); | |
624 | } | |
625 | else | |
626 | { | |
627 | char *bname = get_basename (lo_name); | |
628 | char *fnm = dbe_sprintf ("%.*s/%s", (int) (bname - lo_name), lo_name, nm); | |
629 | df = new DbeFile (fnm); | |
630 | df->filetype |= (DbeFile::F_FILE | DbeFile::F_DEBUG_FILE); | |
631 | free (fnm); | |
632 | } | |
633 | Dprintf (DEBUG_STABS, "get_related_file: %s -> '%s'\n", nm, df->get_name ()); | |
634 | Elf_status st = ELF_ERR_CANT_OPEN_FILE; | |
635 | Elf *elf = elf_begin (df->get_location (), &st); | |
636 | if (elf) | |
637 | { | |
638 | elf->dbeFile = df; | |
639 | return elf; | |
640 | } | |
641 | switch (st) | |
642 | { | |
643 | case ELF_ERR_CANT_OPEN_FILE: | |
644 | append_msg (CMSG_ERROR, GTXT ("Cannot open file `%s'"), df->get_name ()); | |
645 | break; | |
646 | case ELF_ERR_BAD_ELF_FORMAT: | |
647 | default: | |
648 | append_msg (CMSG_ERROR, GTXT ("Cannot read ELF header of `%s'"), | |
649 | df->get_name ()); | |
650 | break; | |
651 | } | |
652 | delete df; | |
653 | return NULL; | |
654 | } | |
655 | ||
656 | Elf * | |
657 | Elf::find_ancillary_files (char *lo_name) | |
658 | { | |
659 | // read the .gnu_debuglink and .SUNW_ancillary seections | |
660 | if (gnu_debug_file) | |
661 | return gnu_debug_file; | |
662 | unsigned int sec = elf_get_sec_num (NTXT (".gnu_debuglink")); | |
663 | if (sec > 0) | |
664 | { | |
665 | Elf_Data *dp = elf_getdata (sec); | |
666 | if (dp) | |
667 | { | |
668 | gnu_debug_file = get_related_file (lo_name, (char *) (dp->d_buf)); | |
669 | if (gnu_debug_file) | |
670 | return gnu_debug_file; | |
671 | } | |
672 | } | |
673 | ||
674 | sec = elf_get_sec_num (NTXT (".SUNW_ancillary")); | |
675 | if (sec > 0) | |
676 | { | |
677 | Elf_Internal_Shdr *shdr = get_shdr (sec); | |
678 | uint64_t check_sum = 0; | |
679 | char *ancName = NULL; | |
680 | if (shdr) | |
681 | { | |
682 | Elf_Data *dp = elf_getdata (sec); | |
683 | for (int i = 0, sz = (int) (shdr->sh_size / shdr->sh_entsize); | |
684 | i < sz; i++) | |
685 | { | |
686 | Elf64_Ancillary anc; | |
687 | if (elf_getancillary (dp, i, &anc) == NULL | |
688 | || anc.a_tag == ANC_SUNW_NULL) | |
689 | break; | |
690 | if (anc.a_tag == ANC_SUNW_MEMBER) | |
691 | ancName = elf_strptr (shdr->sh_link, anc.a_un.a_ptr); | |
692 | else if (anc.a_tag == ANC_SUNW_CHECKSUM) | |
693 | { | |
694 | if (i == 0) | |
695 | { | |
696 | check_sum = anc.a_un.a_val; | |
697 | continue; | |
698 | } | |
699 | if (check_sum == anc.a_un.a_val) | |
700 | ancName = NULL; | |
701 | if (ancName) | |
702 | { | |
703 | Elf *ancElf = get_related_file (lo_name, ancName); | |
704 | if (ancElf == NULL) | |
705 | continue; | |
706 | int ancSec = ancElf->elf_get_sec_num (".SUNW_ancillary"); | |
707 | if (ancSec > 0) | |
708 | { | |
709 | Elf_Internal_Shdr *ancHdr = ancElf->get_shdr (ancSec); | |
710 | if (ancHdr) | |
711 | { | |
712 | Elf_Data *anc_dp = ancElf->elf_getdata (ancSec); | |
713 | Elf64_Ancillary anc1; | |
714 | if (ancElf->elf_getancillary (anc_dp, 0, &anc1) | |
715 | && (anc1.a_tag == ANC_SUNW_CHECKSUM) && | |
716 | anc1.a_un.a_val == anc.a_un.a_val) | |
717 | { | |
718 | if (ancillary_files == NULL) | |
719 | ancillary_files = new Vector<Elf*>(2); | |
720 | ancillary_files->append (ancElf); | |
721 | } | |
722 | else | |
723 | append_msg (CMSG_WARN, GTXT ("Load Object: '%s' (checksum Ox%lld). The .anc file '%s' has checksum Ox%llx"), | |
724 | STR (fname), (long long) check_sum, | |
725 | STR (ancElf->dbeFile->get_location ()), | |
726 | (long long) anc1.a_un.a_val); | |
727 | } | |
728 | } | |
729 | ancName = NULL; | |
730 | } | |
731 | } | |
732 | } | |
733 | } | |
734 | } | |
735 | return NULL; | |
736 | } | |
737 | ||
7434de7e VM |
738 | void |
739 | Elf::get_bfd_symbols() | |
740 | { | |
741 | if (bfd_symcnt < 0) | |
742 | { | |
743 | if ((bfd_get_file_flags (abfd) & HAS_SYMS) != 0) | |
744 | bfd_symcnt = bfd_get_symtab_upper_bound (abfd); | |
745 | if (bfd_symcnt > 0) | |
746 | { | |
747 | bfd_sym = (asymbol **) malloc (bfd_symcnt); | |
748 | bfd_symcnt = bfd_canonicalize_symtab (abfd, bfd_sym); | |
749 | if (bfd_symcnt < 0) | |
750 | { | |
751 | free (bfd_sym); | |
752 | bfd_sym = NULL; | |
753 | } | |
754 | } | |
755 | else | |
756 | bfd_symcnt = 0; | |
757 | } | |
758 | ||
759 | if (bfd_dynsymcnt < 0) | |
760 | { | |
761 | bfd_dynsymcnt = bfd_get_dynamic_symtab_upper_bound (abfd); | |
762 | if (bfd_dynsymcnt > 0) | |
763 | { | |
764 | bfd_dynsym = (asymbol **) malloc (bfd_dynsymcnt); | |
765 | bfd_dynsymcnt = bfd_canonicalize_dynamic_symtab (abfd, bfd_dynsym); | |
766 | if (bfd_dynsymcnt < 0) | |
767 | { | |
768 | free (bfd_dynsym); | |
769 | bfd_dynsym = NULL; | |
770 | } | |
771 | } | |
772 | else | |
773 | bfd_dynsymcnt = 0; | |
774 | } | |
775 | if (bfd_synthcnt < 0) | |
776 | { | |
777 | bfd_synthcnt = bfd_get_synthetic_symtab (abfd, bfd_symcnt, bfd_sym, | |
778 | bfd_dynsymcnt, bfd_dynsym, &bfd_synthsym); | |
779 | if (bfd_synthcnt < 0) | |
780 | bfd_synthcnt = 0; | |
781 | } | |
782 | } | |
783 | ||
784 | static int | |
785 | cmp_sym_addr (const void *a, const void *b) | |
786 | { | |
787 | asymbol *sym1 = *((asymbol **) a); | |
788 | asymbol *sym2 = *((asymbol **) b); | |
789 | uint64_t a1 = sym1->value; | |
790 | uint64_t a2 = sym2->value; | |
791 | if (sym1->section) | |
792 | a1 += sym1->section->vma; | |
793 | if (sym2->section) | |
794 | a2 += sym2->section->vma; | |
795 | return a1 < a2 ? -1 : (a1 == a2 ? 0 : 1); | |
796 | } | |
797 | ||
798 | const char * | |
799 | Elf::get_funcname_in_plt (uint64_t pc) | |
800 | { | |
801 | if (synthsym == NULL) | |
802 | { | |
803 | get_bfd_symbols(); | |
804 | synthsym = new Vector<asymbol *> (bfd_synthcnt + 1); | |
805 | for (long i = 0; i < bfd_synthcnt; i++) | |
806 | synthsym->append (bfd_synthsym + i); | |
807 | synthsym->sort (cmp_sym_addr); | |
808 | } | |
809 | ||
810 | asymbol sym, *symp = &sym; | |
811 | sym.section = NULL; | |
812 | sym.value = pc; | |
813 | long ind = synthsym->bisearch (0, -1, &symp, cmp_sym_addr); | |
814 | if (ind >= 0) | |
815 | return synthsym->get (ind)->name; | |
816 | return NULL; | |
817 | } | |
818 | ||
bb368aad VM |
819 | char* |
820 | Elf::get_location () | |
821 | { | |
822 | return dbeFile ? dbeFile->get_location () : fname; | |
823 | } | |
824 | ||
825 | #define RET_S(x) if (t == x) return (char *) #x | |
826 | ||
827 | static char * | |
828 | get_elf_class_name (int t) | |
829 | { | |
830 | RET_S (ELFCLASSNONE); | |
831 | RET_S (ELFCLASS32); | |
832 | RET_S (ELFCLASS64); | |
833 | return NTXT ("ELFCLASS_UNKNOWN"); | |
834 | } | |
835 | ||
836 | static char * | |
837 | get_elf_data_name (int t) | |
838 | { | |
839 | RET_S (ELFDATANONE); | |
840 | RET_S (ELFDATA2LSB); | |
841 | RET_S (ELFDATA2MSB); | |
842 | return NTXT ("ELFDATA_UNKNOWN"); | |
843 | } | |
844 | ||
845 | static char * | |
846 | get_elf_osabi_name (int t) | |
847 | { | |
848 | RET_S (ELFOSABI_NONE); | |
849 | RET_S (ELFOSABI_HPUX); | |
850 | RET_S (ELFOSABI_NETBSD); | |
851 | RET_S (ELFOSABI_LINUX); | |
852 | RET_S (ELFOSABI_SOLARIS); | |
853 | RET_S (ELFOSABI_AIX); | |
854 | RET_S (ELFOSABI_IRIX); | |
855 | RET_S (ELFOSABI_FREEBSD); | |
856 | RET_S (ELFOSABI_TRU64); | |
857 | RET_S (ELFOSABI_MODESTO); | |
858 | RET_S (ELFOSABI_OPENBSD); | |
859 | return NTXT ("ELFOSABI_UNKNOWN"); | |
860 | } | |
861 | ||
862 | static char * | |
863 | get_elf_etype_name (int t) | |
864 | { | |
865 | RET_S (ET_NONE); | |
866 | RET_S (ET_REL); | |
867 | RET_S (ET_EXEC); | |
868 | RET_S (ET_DYN); | |
869 | RET_S (ET_CORE); | |
870 | RET_S (ET_LOPROC); | |
871 | RET_S (ET_HIPROC); | |
872 | return NTXT ("ETYPE_UNKNOWN"); | |
873 | } | |
874 | ||
875 | static char * | |
876 | get_elf_ptype_name (int t) | |
877 | { | |
878 | RET_S (PT_NULL); | |
879 | RET_S (PT_LOAD); | |
880 | RET_S (PT_DYNAMIC); | |
881 | RET_S (PT_INTERP); | |
882 | RET_S (PT_NOTE); | |
883 | RET_S (PT_SHLIB); | |
884 | RET_S (PT_PHDR); | |
885 | RET_S (PT_TLS); | |
886 | RET_S (PT_LOOS); | |
887 | RET_S (PT_GNU_EH_FRAME); | |
888 | RET_S (PT_GNU_EH_FRAME); | |
889 | RET_S (PT_HIOS); | |
890 | RET_S (PT_LOPROC); | |
891 | RET_S (PT_HIPROC); | |
892 | return NTXT ("PTYPE_UNKNOWN"); | |
893 | } | |
894 | ||
895 | static char * | |
896 | get_elf_shtype_name (unsigned int t) | |
897 | { | |
898 | RET_S (SHT_NULL); | |
899 | RET_S (SHT_PROGBITS); | |
900 | RET_S (SHT_SYMTAB); | |
901 | RET_S (SHT_STRTAB); | |
902 | RET_S (SHT_RELA); | |
903 | RET_S (SHT_HASH); | |
904 | RET_S (SHT_DYNAMIC); | |
905 | RET_S (SHT_NOTE); | |
906 | RET_S (SHT_NOBITS); | |
907 | RET_S (SHT_REL); | |
908 | RET_S (SHT_SHLIB); | |
909 | RET_S (SHT_DYNSYM); | |
910 | RET_S (SHT_INIT_ARRAY); | |
911 | RET_S (SHT_FINI_ARRAY); | |
912 | RET_S (SHT_PREINIT_ARRAY); | |
913 | RET_S (SHT_GROUP); | |
914 | RET_S (SHT_SYMTAB_SHNDX); | |
915 | RET_S (SHT_LOOS); | |
916 | RET_S (SHT_SUNW_verdef); | |
917 | RET_S (SHT_SUNW_verneed); | |
918 | RET_S (SHT_HIOS); | |
919 | RET_S (SHT_LOPROC); | |
920 | RET_S (SHT_HIPROC); | |
921 | RET_S (SHT_LOUSER); | |
922 | RET_S (SHT_HIUSER); | |
923 | return NTXT ("SHTYPE_UNKNOWN"); | |
924 | } | |
925 | ||
926 | static char * | |
927 | get_elf_machine_name (int t) | |
928 | { | |
929 | RET_S (EM_NONE); | |
930 | RET_S (EM_M32); | |
931 | RET_S (EM_SPARC); | |
932 | RET_S (EM_386); | |
933 | RET_S (EM_68K); | |
934 | RET_S (EM_88K); | |
935 | RET_S (EM_860); | |
936 | RET_S (EM_MIPS); | |
937 | RET_S (EM_S370); | |
938 | RET_S (EM_MIPS_RS3_LE); | |
939 | RET_S (EM_SPARC32PLUS); | |
940 | RET_S (EM_960); | |
941 | RET_S (EM_PPC); | |
942 | RET_S (EM_PPC64); | |
943 | RET_S (EM_V800); | |
944 | RET_S (EM_FR20); | |
945 | RET_S (EM_RH32); | |
946 | RET_S (EM_RCE); | |
947 | RET_S (EM_ARM); | |
948 | RET_S (EM_ALPHA); | |
949 | RET_S (EM_SH); | |
950 | RET_S (EM_SPARCV9); | |
951 | RET_S (EM_TRICORE); | |
952 | RET_S (EM_ARC); | |
953 | RET_S (EM_H8_300); | |
954 | RET_S (EM_H8_300H); | |
955 | RET_S (EM_H8S); | |
956 | RET_S (EM_H8_500); | |
957 | RET_S (EM_IA_64); | |
958 | RET_S (EM_MIPS_X); | |
959 | RET_S (EM_COLDFIRE); | |
960 | RET_S (EM_68HC12); | |
961 | RET_S (EM_MMA); | |
962 | RET_S (EM_PCP); | |
963 | RET_S (EM_NCPU); | |
964 | RET_S (EM_NDR1); | |
965 | RET_S (EM_STARCORE); | |
966 | RET_S (EM_ME16); | |
967 | RET_S (EM_ST100); | |
968 | RET_S (EM_TINYJ); | |
969 | RET_S (EM_X86_64); | |
970 | RET_S (EM_PDSP); | |
971 | RET_S (EM_FX66); | |
972 | RET_S (EM_ST9PLUS); | |
973 | RET_S (EM_ST7); | |
974 | RET_S (EM_68HC16); | |
975 | RET_S (EM_68HC11); | |
976 | RET_S (EM_68HC08); | |
977 | RET_S (EM_68HC05); | |
978 | RET_S (EM_SVX); | |
979 | RET_S (EM_ST19); | |
980 | RET_S (EM_VAX); | |
981 | RET_S (EM_CRIS); | |
982 | RET_S (EM_JAVELIN); | |
983 | RET_S (EM_FIREPATH); | |
984 | RET_S (EM_ZSP); | |
985 | RET_S (EM_MMIX); | |
986 | RET_S (EM_HUANY); | |
987 | RET_S (EM_PRISM); | |
988 | RET_S (EM_AVR); | |
989 | RET_S (EM_FR30); | |
990 | RET_S (EM_D10V); | |
991 | RET_S (EM_D30V); | |
992 | RET_S (EM_V850); | |
993 | RET_S (EM_M32R); | |
994 | RET_S (EM_MN10300); | |
995 | RET_S (EM_MN10200); | |
996 | RET_S (EM_PJ); | |
997 | RET_S (EM_OPENRISC); | |
998 | RET_S (EM_XTENSA); | |
999 | return NTXT ("ELFMACHINE_UNKNOWN"); | |
1000 | } | |
1001 | ||
1002 | static char * | |
1003 | get_elf_version_name (int t) | |
1004 | { | |
1005 | RET_S (EV_NONE); | |
1006 | RET_S (EV_CURRENT); | |
1007 | return NTXT ("VERSION_UNKNOWN"); | |
1008 | } | |
1009 | ||
1010 | static char * | |
1011 | get_elf_ancillary_tag (int t) | |
1012 | { | |
1013 | RET_S (ANC_SUNW_NULL); | |
1014 | RET_S (ANC_SUNW_CHECKSUM); | |
1015 | RET_S (ANC_SUNW_MEMBER); | |
1016 | RET_S (ANC_SUNW_NUM); | |
1017 | return NTXT ("ANCILLARY_TAG_UNKNOWN"); | |
1018 | } | |
1019 | ||
1020 | #define ADD_S(x) if ((f & (x)) == (x)) { sb->append(' '); sb->append(#x); f &= ~(x); } | |
1021 | ||
1022 | static void | |
1023 | dump_sh_flags (StringBuilder *sb, long long flags) | |
1024 | { | |
1025 | long long f = flags; | |
1026 | if (f != 0) | |
1027 | { | |
1028 | sb->append (NTXT (" [")); | |
1029 | ADD_S (SHF_WRITE) | |
1030 | ADD_S (SHF_ALLOC) | |
1031 | ADD_S (SHF_EXECINSTR) | |
1032 | ADD_S (SHF_MERGE) | |
1033 | ADD_S (SHF_STRINGS) | |
1034 | ADD_S (SHF_INFO_LINK) | |
1035 | ADD_S (SHF_LINK_ORDER) | |
1036 | ADD_S (SHF_OS_NONCONFORMING) | |
1037 | ADD_S (SHF_GROUP) | |
1038 | ADD_S (SHF_TLS) | |
1039 | ADD_S (SHF_SUNW_ABSENT) | |
1040 | ADD_S (SHF_EXCLUDE) | |
1041 | if (f != 0 && f != flags) | |
1042 | sb->appendf (NTXT (" 0x%llx"), (long long) f); | |
1043 | sb->append (NTXT (" ]")); | |
1044 | } | |
1045 | sb->append (NTXT ("\n")); | |
1046 | } | |
1047 | ||
1048 | static void | |
1049 | dump_p_flags (StringBuilder *sb, long long flags) | |
1050 | { | |
1051 | long long f = flags; | |
1052 | if (f != 0) | |
1053 | { | |
1054 | sb->append (NTXT (" [")); | |
1055 | ADD_S (PF_X) | |
1056 | ADD_S (PF_W) | |
1057 | ADD_S (PF_R) | |
1058 | ADD_S (PF_MASKPROC) | |
1059 | if (f != 0 && f != flags) | |
1060 | sb->appendf (NTXT (" 0x%llx"), (long long) f); | |
1061 | sb->append (NTXT (" ]")); | |
1062 | } | |
1063 | sb->append (NTXT ("\n")); | |
1064 | } | |
1065 | ||
1066 | char * | |
1067 | Elf::dump () | |
1068 | { | |
1069 | StringBuilder sb; | |
1070 | sb.sprintf (NTXT ("ELF Header: %s\n"), fname ? fname : GTXT ("(unknown)")); | |
1071 | if (ehdrp == NULL) | |
1072 | { | |
1073 | sb.appendf (GTXT ("\n\n Cannot read Elf header\n")); | |
1074 | return sb.toString (); | |
1075 | } | |
1076 | sb.appendf (NTXT (" %-15s "), NTXT ("e_ident")); | |
1077 | for (int i = 0; i < EI_NIDENT; i++) | |
1078 | sb.appendf (NTXT ("%x"), ehdrp->e_ident[i]); | |
1079 | sb.append (NTXT ("\n")); | |
1080 | char *fmt0 = NTXT (" %-15s %10lld ( %s )\n"); | |
1081 | char *fmt1 = NTXT (" %-15s 0x%08llx ( %lld )\n"); | |
1082 | char *fmt2 = NTXT (" %-15s 0x%08llx"); | |
1083 | sb.appendf (fmt0, NTXT ("EI_CLASS"), (long long) ehdrp->e_ident[EI_CLASS], | |
1084 | get_elf_class_name (ehdrp->e_ident[EI_CLASS])); | |
1085 | sb.appendf (fmt0, NTXT ("EI_DATA"), (long long) ehdrp->e_ident[EI_DATA], | |
1086 | get_elf_data_name (ehdrp->e_ident[EI_DATA])); | |
1087 | sb.appendf (fmt0, NTXT ("EI_OSABI"), (long long) ehdrp->e_ident[EI_OSABI], | |
1088 | get_elf_osabi_name (ehdrp->e_ident[EI_OSABI])); | |
1089 | sb.appendf (fmt0, NTXT ("e_type"), (long long) ehdrp->e_type, | |
1090 | get_elf_etype_name (ehdrp->e_type)); | |
1091 | sb.appendf (fmt0, NTXT ("e_machine"), (long long) ehdrp->e_machine, | |
1092 | get_elf_machine_name (ehdrp->e_machine)); | |
1093 | sb.appendf (fmt0, NTXT ("e_version"), (long long) ehdrp->e_version, | |
1094 | get_elf_version_name (ehdrp->e_version)); | |
1095 | sb.appendf (fmt1, NTXT ("e_entry"), (long long) ehdrp->e_entry, | |
1096 | (long long) ehdrp->e_entry); | |
1097 | sb.appendf (fmt1, NTXT ("e_phoff"), (long long) ehdrp->e_phoff, | |
1098 | (long long) ehdrp->e_phoff); | |
1099 | sb.appendf (fmt1, NTXT ("e_shoff"), (long long) ehdrp->e_shoff, | |
1100 | (long long) ehdrp->e_shoff); | |
1101 | sb.appendf (fmt1, NTXT ("e_flags"), (long long) ehdrp->e_flags, | |
1102 | (long long) ehdrp->e_flags); | |
1103 | sb.appendf (fmt1, NTXT ("e_ehsize"), (long long) ehdrp->e_ehsize, | |
1104 | (long long) ehdrp->e_ehsize); | |
1105 | sb.appendf (fmt1, NTXT ("e_phentsize"), (long long) ehdrp->e_phentsize, | |
1106 | (long long) ehdrp->e_phentsize); | |
1107 | sb.appendf (fmt1, NTXT ("e_phnum"), (long long) ehdrp->e_phnum, | |
1108 | (long long) ehdrp->e_phnum); | |
1109 | sb.appendf (fmt1, NTXT ("e_shentsize"), (long long) ehdrp->e_shentsize, | |
1110 | (long long) ehdrp->e_shentsize); | |
1111 | sb.appendf (fmt1, NTXT ("e_shnum"), (long long) ehdrp->e_shnum, | |
1112 | (long long) ehdrp->e_shnum); | |
1113 | sb.appendf (fmt1, NTXT ("e_shstrndx"), (long long) ehdrp->e_shstrndx, | |
1114 | (long long) ehdrp->e_shstrndx); | |
1115 | ||
1116 | for (unsigned int i = 0; i < ehdrp->e_phnum; i++) | |
1117 | { | |
1118 | sb.appendf (NTXT ("\nProgram Header[%d]:\n"), i); | |
1119 | Elf_Internal_Phdr *phdr = get_phdr (i); | |
1120 | if (phdr == NULL) | |
1121 | { | |
1122 | sb.appendf (NTXT (" ERROR: get_phdr(%d) failed\n"), i); | |
1123 | continue; | |
1124 | } | |
1125 | sb.appendf (fmt0, "p_type", (long long) phdr->p_type, | |
1126 | get_elf_ptype_name (phdr->p_type)); | |
1127 | sb.appendf (fmt2, "p_flags", (long long) phdr->p_flags); | |
1128 | dump_p_flags (&sb, phdr->p_flags); | |
1129 | sb.appendf (fmt1, "p_offset", (long long) phdr->p_offset, | |
1130 | (long long) phdr->p_offset); | |
1131 | sb.appendf (fmt1, "p_vaddr", (long long) phdr->p_vaddr, | |
1132 | (long long) phdr->p_vaddr); | |
1133 | sb.appendf (fmt1, "p_paddr", (long long) phdr->p_paddr, | |
1134 | (long long) phdr->p_paddr); | |
1135 | sb.appendf (fmt1, "p_filesz", (long long) phdr->p_filesz, | |
1136 | (long long) phdr->p_filesz); | |
1137 | sb.appendf (fmt1, "p_memsz", (long long) phdr->p_memsz, | |
1138 | (long long) phdr->p_memsz); | |
1139 | sb.appendf (fmt1, "p_align", (long long) phdr->p_align, | |
1140 | (long long) phdr->p_align); | |
1141 | } | |
1142 | ||
1143 | for (unsigned int i = 1; i < ehdrp->e_shnum; i++) | |
1144 | { | |
1145 | sb.appendf (NTXT ("\nSection Header[%d]:\n"), i); | |
1146 | Elf_Internal_Shdr *shdr = get_shdr (i); | |
1147 | if (shdr == NULL) | |
1148 | { | |
1149 | sb.appendf (NTXT (" ERROR: get_shdr(%d) failed\n"), i); | |
1150 | continue; | |
1151 | } | |
1152 | char *s = get_sec_name (i); | |
1153 | sb.appendf (fmt0, "sh_name", (long long) shdr->sh_name, | |
1154 | s ? s : NTXT ("NULL")); | |
1155 | sb.appendf (fmt0, "sh_type", (long long) shdr->sh_type, | |
1156 | get_elf_shtype_name (shdr->sh_type)); | |
1157 | sb.appendf (fmt2, "sh_flags", (long long) shdr->sh_flags); | |
1158 | dump_sh_flags (&sb, shdr->sh_flags); | |
1159 | sb.appendf (fmt1, "sh_addr", (long long) shdr->sh_addr, | |
1160 | (long long) shdr->sh_addr); | |
1161 | sb.appendf (fmt1, "sh_offset", (long long) shdr->sh_offset, | |
1162 | (long long) shdr->sh_offset); | |
1163 | sb.appendf (fmt1, "sh_size", (long long) shdr->sh_size, | |
1164 | (long long) shdr->sh_size); | |
1165 | sb.appendf (fmt1, "sh_link", (long long) shdr->sh_link, | |
1166 | (long long) shdr->sh_link); | |
1167 | sb.appendf (fmt1, "sh_info", (long long) shdr->sh_info, | |
1168 | (long long) shdr->sh_info); | |
1169 | sb.appendf (fmt1, "sh_addralign", (long long) shdr->sh_addralign, | |
1170 | (long long) shdr->sh_addralign); | |
1171 | sb.appendf (fmt1, "sh_entsize", (long long) shdr->sh_entsize, | |
1172 | (long long) shdr->sh_entsize); | |
1173 | } | |
1174 | ||
1175 | for (unsigned int i = 1; i < ehdrp->e_shnum; i++) | |
1176 | { | |
1177 | Elf_Internal_Shdr *shdr = get_shdr (i); | |
1178 | if (shdr == NULL) | |
1179 | continue; | |
1180 | char *secName = get_sec_name (i); | |
1181 | if (secName == NULL) | |
1182 | continue; | |
1183 | if (strcmp (NTXT (".SUNW_ancillary"), secName) == 0) | |
1184 | { | |
1185 | sb.appendf (NTXT ("\nSection[%d]: %s\n"), i, secName); | |
1186 | Elf_Data *dp = elf_getdata (i); | |
1187 | for (int j = 0, cnt = (int) (shdr->sh_size / shdr->sh_entsize); | |
1188 | j < cnt; j++) | |
1189 | { | |
1190 | Elf64_Ancillary anc; | |
1191 | if (elf_getancillary (dp, j, &anc) == NULL) | |
1192 | break; | |
1193 | sb.appendf (NTXT ("%10d %-20s 0x%08llx %6lld"), j, | |
1194 | get_elf_ancillary_tag ((int) anc.a_tag), | |
1195 | (long long) anc.a_un.a_ptr, (long long) anc.a_un.a_ptr); | |
1196 | if (anc.a_tag == ANC_SUNW_MEMBER) | |
1197 | sb.appendf (NTXT (" %s\n"), STR (elf_strptr (shdr->sh_link, anc.a_un.a_ptr))); | |
1198 | else | |
1199 | sb.append (NTXT ("\n")); | |
1200 | } | |
1201 | } | |
1202 | } | |
1203 | return sb.toString (); | |
1204 | } | |
1205 | ||
1206 | void | |
1207 | Elf::dump_elf_sec () | |
1208 | { | |
1209 | if (!DUMP_ELF_SEC) | |
1210 | return; | |
1211 | if (ehdrp == NULL) | |
1212 | return; | |
1213 | Dprintf (DUMP_ELF_SEC, "======= DwarfLib::dump_elf_sec\n" | |
1214 | " N |type|flags| sh_addr | sh_offset | sh_size | sh_link |" | |
1215 | " sh_info | sh_addralign | sh_entsize | sh_name | name\n"); | |
1216 | for (unsigned int sec = 1; sec < ehdrp->e_shnum; sec++) | |
1217 | { | |
1218 | Elf_Internal_Shdr *shdr = get_shdr (sec); | |
1219 | if (shdr == NULL) | |
1220 | continue; | |
1221 | char *name = elf_strptr (ehdrp->e_shstrndx, shdr->sh_name); | |
1222 | Dprintf (DUMP_ELF_SEC, "%3d:%3d |%4d |%9lld | %9lld |%8lld |%8lld |" | |
1223 | "%8lld |%14d |%11lld | %6lld %s\n", | |
1224 | sec, (int) shdr->sh_type, (int) shdr->sh_flags, | |
1225 | (long long) shdr->sh_addr, (long long) shdr->sh_offset, | |
1226 | (long long) shdr->sh_size, (long long) shdr->sh_link, | |
1227 | (long long) shdr->sh_info, | |
1228 | (int) shdr->sh_addralign, (long long) shdr->sh_entsize, | |
1229 | (long long) shdr->sh_name, name ? name : NTXT ("NULL")); | |
1230 | } | |
1231 | Dprintf (DUMP_ELF_SEC, NTXT ("\n")); | |
1232 | } |