1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>
7 #include <asm/orc_types.h>
8 #include <objtool/objtool.h>
9 #include <objtool/orc.h>
10 #include <objtool/warn.h>
11 #include <objtool/endianness.h>
13 int orc_dump(const char *_objname
)
15 int fd
, nr_entries
, i
, *orc_ip
= NULL
, orc_size
= 0;
16 struct orc_entry
*orc
= NULL
;
19 Elf64_Addr orc_ip_addr
= 0;
20 size_t shstrtab_idx
, strtab_idx
= 0;
26 Elf_Data
*data
, *symtab
= NULL
, *rela_orc_ip
= NULL
;
27 struct elf dummy_elf
= {};
32 elf_version(EV_CURRENT
);
34 fd
= open(objname
, O_RDONLY
);
40 elf
= elf_begin(fd
, ELF_C_READ_MMAP
, NULL
);
42 WARN_ELF("elf_begin");
46 if (!elf64_getehdr(elf
)) {
47 WARN_ELF("elf64_getehdr");
50 memcpy(&dummy_elf
.ehdr
, elf64_getehdr(elf
), sizeof(dummy_elf
.ehdr
));
52 if (elf_getshdrnum(elf
, &nr_sections
)) {
53 WARN_ELF("elf_getshdrnum");
57 if (elf_getshdrstrndx(elf
, &shstrtab_idx
)) {
58 WARN_ELF("elf_getshdrstrndx");
62 for (i
= 0; i
< nr_sections
; i
++) {
63 scn
= elf_getscn(elf
, i
);
65 WARN_ELF("elf_getscn");
69 if (!gelf_getshdr(scn
, &sh
)) {
70 WARN_ELF("gelf_getshdr");
74 name
= elf_strptr(elf
, shstrtab_idx
, sh
.sh_name
);
76 WARN_ELF("elf_strptr");
80 data
= elf_getdata(scn
, NULL
);
82 WARN_ELF("elf_getdata");
86 if (!strcmp(name
, ".symtab")) {
88 } else if (!strcmp(name
, ".strtab")) {
90 } else if (!strcmp(name
, ".orc_unwind")) {
92 orc_size
= sh
.sh_size
;
93 } else if (!strcmp(name
, ".orc_unwind_ip")) {
95 orc_ip_addr
= sh
.sh_addr
;
96 } else if (!strcmp(name
, ".rela.orc_unwind_ip")) {
101 if (!symtab
|| !strtab_idx
|| !orc
|| !orc_ip
)
104 if (orc_size
% sizeof(*orc
) != 0) {
105 WARN("bad .orc_unwind section size");
109 nr_entries
= orc_size
/ sizeof(*orc
);
110 for (i
= 0; i
< nr_entries
; i
++) {
112 if (!gelf_getrela(rela_orc_ip
, i
, &rela
)) {
113 WARN_ELF("gelf_getrela");
117 if (!gelf_getsym(symtab
, GELF_R_SYM(rela
.r_info
), &sym
)) {
118 WARN_ELF("gelf_getsym");
122 if (GELF_ST_TYPE(sym
.st_info
) == STT_SECTION
) {
123 scn
= elf_getscn(elf
, sym
.st_shndx
);
125 WARN_ELF("elf_getscn");
129 if (!gelf_getshdr(scn
, &sh
)) {
130 WARN_ELF("gelf_getshdr");
134 name
= elf_strptr(elf
, shstrtab_idx
, sh
.sh_name
);
136 WARN_ELF("elf_strptr");
140 name
= elf_strptr(elf
, strtab_idx
, sym
.st_name
);
142 WARN_ELF("elf_strptr");
147 printf("%s+%llx:", name
, (unsigned long long)rela
.r_addend
);
150 printf("%llx:", (unsigned long long)(orc_ip_addr
+ (i
* sizeof(int)) + orc_ip
[i
]));
153 orc_print_dump(&dummy_elf
, orc
, i
);