Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/objtool/orc_dump.c
49070 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Copyright (C) 2017 Josh Poimboeuf <[email protected]>
4
*/
5
6
#include <unistd.h>
7
#include <asm/orc_types.h>
8
#include <objtool/objtool.h>
9
#include <objtool/orc.h>
10
#include <objtool/warn.h>
11
12
int orc_dump(const char *filename)
13
{
14
int fd, nr_entries, i, *orc_ip = NULL, orc_size = 0;
15
struct orc_entry *orc = NULL;
16
char *name;
17
size_t nr_sections;
18
Elf64_Addr orc_ip_addr = 0;
19
size_t shstrtab_idx, strtab_idx = 0;
20
Elf *elf;
21
Elf_Scn *scn;
22
GElf_Shdr sh;
23
GElf_Rela rela;
24
GElf_Sym sym;
25
Elf_Data *data, *symtab = NULL, *rela_orc_ip = NULL;
26
struct elf dummy_elf = {};
27
28
elf_version(EV_CURRENT);
29
30
fd = open(filename, O_RDONLY);
31
if (fd == -1) {
32
perror("open");
33
return -1;
34
}
35
36
elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
37
if (!elf) {
38
ERROR_ELF("elf_begin");
39
return -1;
40
}
41
42
if (!elf64_getehdr(elf)) {
43
ERROR_ELF("elf64_getehdr");
44
return -1;
45
}
46
memcpy(&dummy_elf.ehdr, elf64_getehdr(elf), sizeof(dummy_elf.ehdr));
47
48
if (elf_getshdrnum(elf, &nr_sections)) {
49
ERROR_ELF("elf_getshdrnum");
50
return -1;
51
}
52
53
if (elf_getshdrstrndx(elf, &shstrtab_idx)) {
54
ERROR_ELF("elf_getshdrstrndx");
55
return -1;
56
}
57
58
for (i = 0; i < nr_sections; i++) {
59
scn = elf_getscn(elf, i);
60
if (!scn) {
61
ERROR_ELF("elf_getscn");
62
return -1;
63
}
64
65
if (!gelf_getshdr(scn, &sh)) {
66
ERROR_ELF("gelf_getshdr");
67
return -1;
68
}
69
70
name = elf_strptr(elf, shstrtab_idx, sh.sh_name);
71
if (!name) {
72
ERROR_ELF("elf_strptr");
73
return -1;
74
}
75
76
data = elf_getdata(scn, NULL);
77
if (!data) {
78
ERROR_ELF("elf_getdata");
79
return -1;
80
}
81
82
if (!strcmp(name, ".symtab")) {
83
symtab = data;
84
} else if (!strcmp(name, ".strtab")) {
85
strtab_idx = i;
86
} else if (!strcmp(name, ".orc_unwind")) {
87
orc = data->d_buf;
88
orc_size = sh.sh_size;
89
} else if (!strcmp(name, ".orc_unwind_ip")) {
90
orc_ip = data->d_buf;
91
orc_ip_addr = sh.sh_addr;
92
} else if (!strcmp(name, ".rela.orc_unwind_ip")) {
93
rela_orc_ip = data;
94
}
95
}
96
97
if (!symtab || !strtab_idx || !orc || !orc_ip)
98
return 0;
99
100
if (orc_size % sizeof(*orc) != 0) {
101
ERROR("bad .orc_unwind section size");
102
return -1;
103
}
104
105
nr_entries = orc_size / sizeof(*orc);
106
for (i = 0; i < nr_entries; i++) {
107
if (rela_orc_ip) {
108
if (!gelf_getrela(rela_orc_ip, i, &rela)) {
109
ERROR_ELF("gelf_getrela");
110
return -1;
111
}
112
113
if (!gelf_getsym(symtab, GELF_R_SYM(rela.r_info), &sym)) {
114
ERROR_ELF("gelf_getsym");
115
return -1;
116
}
117
118
if (GELF_ST_TYPE(sym.st_info) == STT_SECTION) {
119
scn = elf_getscn(elf, sym.st_shndx);
120
if (!scn) {
121
ERROR_ELF("elf_getscn");
122
return -1;
123
}
124
125
if (!gelf_getshdr(scn, &sh)) {
126
ERROR_ELF("gelf_getshdr");
127
return -1;
128
}
129
130
name = elf_strptr(elf, shstrtab_idx, sh.sh_name);
131
if (!name) {
132
ERROR_ELF("elf_strptr");
133
return -1;
134
}
135
} else {
136
name = elf_strptr(elf, strtab_idx, sym.st_name);
137
if (!name) {
138
ERROR_ELF("elf_strptr");
139
return -1;
140
}
141
}
142
143
printf("%s+%llx:", name, (unsigned long long)rela.r_addend);
144
145
} else {
146
printf("%llx:", (unsigned long long)(orc_ip_addr + (i * sizeof(int)) + orc_ip[i]));
147
}
148
149
orc_print_dump(&dummy_elf, orc, i);
150
}
151
152
elf_end(elf);
153
close(fd);
154
155
return 0;
156
}
157
158