]> git.proxmox.com Git - efi-boot-shim.git/blame - buildid.c
debian/rules, debian/shim.install: make sure the 'make install' step does what it...
[efi-boot-shim.git] / buildid.c
CommitLineData
ab881f03
MTL
1/*
2 * Walk a list of input files, printing the name and buildid of any file
3 * that has one.
4 *
5 * This program is licensed under the GNU Public License version 2.
6 */
7
8#include <err.h>
9#include <sys/types.h>
10#include <sys/stat.h>
11#include <fcntl.h>
12#include <getopt.h>
13#include <stdlib.h>
14#include <stdio.h>
15#include <string.h>
16#include <unistd.h>
17#include <libelf.h>
18#include <gelf.h>
19
20static Elf_Scn *get_scn_named(Elf * elf, char *goal, GElf_Shdr * shdrp_out)
21{
22 int rc;
23 size_t shstrndx = -1;
24 int scn_no = 0;
25 Elf_Scn *scn = NULL;
26 GElf_Shdr shdr_data, *shdrp;
27
28 shdrp = shdrp_out ? shdrp_out : &shdr_data;
29
30 rc = elf_getshdrstrndx(elf, &shstrndx);
31 if (rc < 0)
32 return NULL;
33
34 do {
35 GElf_Shdr *shdr;
36 char *name;
37
38 scn = elf_getscn(elf, ++scn_no);
39 if (!scn)
40 break;
41
42 shdr = gelf_getshdr(scn, shdrp);
43 if (!shdr)
44 /*
45 * the binary is malformed, but hey, maybe the next
46 * one is fine, why not...
47 */
48 continue;
49
50 name = elf_strptr(elf, shstrndx, shdr->sh_name);
51 if (name && !strcmp(name, goal))
52 return scn;
53 } while (scn != NULL);
54 return NULL;
55}
56
57static void *get_buildid(Elf * elf, size_t * sz)
58{
59 Elf_Scn *scn;
60 size_t notesz;
61 size_t offset = 0;
62 Elf_Data *data;
63 GElf_Shdr shdr;
64
65 scn = get_scn_named(elf, ".note.gnu.build-id", &shdr);
66 if (!scn)
67 return NULL;
68
69 data = elf_getdata(scn, NULL);
70 if (!data)
71 return NULL;
72
73 do {
74 size_t nameoff;
75 size_t descoff;
76 GElf_Nhdr nhdr;
77 char *name;
78
79 notesz = gelf_getnote(data, offset, &nhdr, &nameoff, &descoff);
80 if (!notesz)
81 break;
82 offset += notesz;
83
84 if (nhdr.n_type != NT_GNU_BUILD_ID)
85 continue;
86
87 name = data->d_buf + nameoff;
88 if (!name || strcmp(name, ELF_NOTE_GNU))
89 continue;
90
91 *sz = nhdr.n_descsz;
92 return data->d_buf + descoff;
93 } while (notesz);
94 return NULL;
95}
96
97static void data2hex(uint8_t * data, size_t ds, char *str)
98{
99 const char hex[] = "0123456789abcdef";
100 int s;
101 unsigned int d;
102 for (d = 0, s = 0; d < ds; d += 1, s += 2) {
103 str[s + 0] = hex[(data[d] >> 4) & 0x0f];
104 str[s + 1] = hex[(data[d] >> 0) & 0x0f];
105 }
106 str[s] = '\0';
107}
108
109static void handle_one(char *f)
110{
111 int fd;
112 Elf *elf;
113 char *b = NULL;
114 size_t sz;
115 uint8_t *data;
116
117 if (!strcmp(f, "-")) {
118 fd = STDIN_FILENO;
119
120 if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
121 errx(1, "Couldn't read ELF data from \"%s\"", f);
122 } else {
123 if ((fd = open(f, O_RDONLY)) < 0)
124 err(1, "Couldn't open \"%s\"", f);
125
126 if ((elf = elf_begin(fd, ELF_C_READ_MMAP, NULL)) == NULL)
127 errx(1, "Couldn't read ELF data from \"%s\"", f);
128 }
129
130 data = get_buildid(elf, &sz);
131 if (data) {
132 b = alloca(sz * 2 + 1);
133 data2hex(data, sz, b);
134 if (b) {
135 write(1, f, strlen(f));
136 write(1, " ", 1);
137 write(1, b, strlen(b));
138 write(1, "\n", 1);
139 }
140 }
141 elf_end(elf);
142 close(fd);
143}
144
145static void
146 __attribute__ ((__noreturn__))
147 usage(int status)
148{
149 FILE *out = status ? stderr : stdout;
150
151 fprintf(out, "Usage: buildid [ flags | file0 [file1 [.. fileN]]]\n");
152 fprintf(out, "Flags:\n");
153 fprintf(out, " -h Print this help text and exit\n");
154
155 exit(status);
156}
157
158int main(int argc, char **argv)
159{
160 int i;
161 struct option options[] = {
162 {.name = "help",
163 .val = '?',
164 },
165 {.name = "usage",
166 .val = '?',
167 },
168 {.name = ""}
169 };
170 int longindex = -1;
171
172 while ((i = getopt_long(argc, argv, "h", options, &longindex)) != -1) {
173 switch (i) {
174 case 'h':
175 case '?':
176 usage(longindex == -1 ? 1 : 0);
177 break;
178 }
179 }
180
181 elf_version(EV_CURRENT);
182
183 if (optind == argc)
184 usage(1);
185
186 for (i = optind; i < argc; i++)
187 handle_one(argv[i]);
188
189 return 0;
190}
191
192// vim:fenc=utf-8:tw=75