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