1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com>
10 static const char *reg_name(unsigned int reg
)
27 case ORC_REG_BP_INDIRECT
:
29 case ORC_REG_SP_INDIRECT
:
36 static const char *orc_type_name(unsigned int type
)
43 case ORC_TYPE_REGS_IRET
:
50 static void print_reg(unsigned int reg
, int offset
)
52 if (reg
== ORC_REG_BP_INDIRECT
)
53 printf("(bp%+d)", offset
);
54 else if (reg
== ORC_REG_SP_INDIRECT
)
55 printf("(sp%+d)", offset
);
56 else if (reg
== ORC_REG_UNDEFINED
)
59 printf("%s%+d", reg_name(reg
), offset
);
62 int orc_dump(const char *_objname
)
64 int fd
, nr_entries
, i
, *orc_ip
= NULL
, orc_size
= 0;
65 struct orc_entry
*orc
= NULL
;
68 Elf64_Addr orc_ip_addr
= 0;
69 size_t shstrtab_idx
, strtab_idx
= 0;
75 Elf_Data
*data
, *symtab
= NULL
, *rela_orc_ip
= NULL
;
80 elf_version(EV_CURRENT
);
82 fd
= open(objname
, O_RDONLY
);
88 elf
= elf_begin(fd
, ELF_C_READ_MMAP
, NULL
);
90 WARN_ELF("elf_begin");
94 if (elf_getshdrnum(elf
, &nr_sections
)) {
95 WARN_ELF("elf_getshdrnum");
99 if (elf_getshdrstrndx(elf
, &shstrtab_idx
)) {
100 WARN_ELF("elf_getshdrstrndx");
104 for (i
= 0; i
< nr_sections
; i
++) {
105 scn
= elf_getscn(elf
, i
);
107 WARN_ELF("elf_getscn");
111 if (!gelf_getshdr(scn
, &sh
)) {
112 WARN_ELF("gelf_getshdr");
116 name
= elf_strptr(elf
, shstrtab_idx
, sh
.sh_name
);
118 WARN_ELF("elf_strptr");
122 data
= elf_getdata(scn
, NULL
);
124 WARN_ELF("elf_getdata");
128 if (!strcmp(name
, ".symtab")) {
130 } else if (!strcmp(name
, ".strtab")) {
132 } else if (!strcmp(name
, ".orc_unwind")) {
134 orc_size
= sh
.sh_size
;
135 } else if (!strcmp(name
, ".orc_unwind_ip")) {
136 orc_ip
= data
->d_buf
;
137 orc_ip_addr
= sh
.sh_addr
;
138 } else if (!strcmp(name
, ".rela.orc_unwind_ip")) {
143 if (!symtab
|| !strtab_idx
|| !orc
|| !orc_ip
)
146 if (orc_size
% sizeof(*orc
) != 0) {
147 WARN("bad .orc_unwind section size");
151 nr_entries
= orc_size
/ sizeof(*orc
);
152 for (i
= 0; i
< nr_entries
; i
++) {
154 if (!gelf_getrela(rela_orc_ip
, i
, &rela
)) {
155 WARN_ELF("gelf_getrela");
159 if (!gelf_getsym(symtab
, GELF_R_SYM(rela
.r_info
), &sym
)) {
160 WARN_ELF("gelf_getsym");
164 if (GELF_ST_TYPE(sym
.st_info
) == STT_SECTION
) {
165 scn
= elf_getscn(elf
, sym
.st_shndx
);
167 WARN_ELF("elf_getscn");
171 if (!gelf_getshdr(scn
, &sh
)) {
172 WARN_ELF("gelf_getshdr");
176 name
= elf_strptr(elf
, shstrtab_idx
, sh
.sh_name
);
178 WARN_ELF("elf_strptr");
182 name
= elf_strptr(elf
, strtab_idx
, sym
.st_name
);
184 WARN_ELF("elf_strptr");
189 printf("%s+%llx:", name
, (unsigned long long)rela
.r_addend
);
192 printf("%llx:", (unsigned long long)(orc_ip_addr
+ (i
* sizeof(int)) + orc_ip
[i
]));
198 print_reg(orc
[i
].sp_reg
, orc
[i
].sp_offset
);
202 print_reg(orc
[i
].bp_reg
, orc
[i
].bp_offset
);
204 printf(" type:%s end:%d\n",
205 orc_type_name(orc
[i
].type
), orc
[i
].end
);