Merge tag 'sound-5.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
[sfrench/cifs-2.6.git] / tools / perf / util / genelf.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * genelf.c
4  * Copyright (C) 2014, Google, Inc
5  *
6  * Contributed by:
7  *      Stephane Eranian <eranian@gmail.com>
8  */
9
10 #include <sys/types.h>
11 #include <stdio.h>
12 #include <getopt.h>
13 #include <stddef.h>
14 #include <libelf.h>
15 #include <string.h>
16 #include <stdlib.h>
17 #include <inttypes.h>
18 #include <limits.h>
19 #include <fcntl.h>
20 #include <err.h>
21 #ifdef HAVE_DWARF_SUPPORT
22 #include <dwarf.h>
23 #endif
24
25 #include "perf.h"
26 #include "genelf.h"
27 #include "../util/jitdump.h"
28
29 #ifndef NT_GNU_BUILD_ID
30 #define NT_GNU_BUILD_ID 3
31 #endif
32
33 #define JVMTI
34
35 #define BUILD_ID_URANDOM /* different uuid for each run */
36
37 #ifdef HAVE_LIBCRYPTO
38
39 #define BUILD_ID_MD5
40 #undef BUILD_ID_SHA     /* does not seem to work well when linked with Java */
41 #undef BUILD_ID_URANDOM /* different uuid for each run */
42
43 #ifdef BUILD_ID_SHA
44 #include <openssl/sha.h>
45 #endif
46
47 #ifdef BUILD_ID_MD5
48 #include <openssl/md5.h>
49 #endif
50 #endif
51
52
53 typedef struct {
54   unsigned int namesz;  /* Size of entry's owner string */
55   unsigned int descsz;  /* Size of the note descriptor */
56   unsigned int type;    /* Interpretation of the descriptor */
57   char         name[0]; /* Start of the name+desc data */
58 } Elf_Note;
59
60 struct options {
61         char *output;
62         int fd;
63 };
64
65 static char shd_string_table[] = {
66         0,
67         '.', 't', 'e', 'x', 't', 0,                     /*  1 */
68         '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', 0, /*  7 */
69         '.', 's', 'y', 'm', 't', 'a', 'b', 0,           /* 17 */
70         '.', 's', 't', 'r', 't', 'a', 'b', 0,           /* 25 */
71         '.', 'n', 'o', 't', 'e', '.', 'g', 'n', 'u', '.', 'b', 'u', 'i', 'l', 'd', '-', 'i', 'd', 0, /* 33 */
72         '.', 'd', 'e', 'b', 'u', 'g', '_', 'l', 'i', 'n', 'e', 0, /* 52 */
73         '.', 'd', 'e', 'b', 'u', 'g', '_', 'i', 'n', 'f', 'o', 0, /* 64 */
74         '.', 'd', 'e', 'b', 'u', 'g', '_', 'a', 'b', 'b', 'r', 'e', 'v', 0, /* 76 */
75         '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', '_', 'h', 'd', 'r', 0, /* 90 */
76         '.', 'e', 'h', '_', 'f', 'r', 'a', 'm', 'e', 0, /* 104 */
77 };
78
79 static struct buildid_note {
80         Elf_Note desc;          /* descsz: size of build-id, must be multiple of 4 */
81         char     name[4];       /* GNU\0 */
82         char     build_id[20];
83 } bnote;
84
85 static Elf_Sym symtab[]={
86         /* symbol 0 MUST be the undefined symbol */
87         { .st_name  = 0, /* index in sym_string table */
88           .st_info  = ELF_ST_TYPE(STT_NOTYPE),
89           .st_shndx = 0, /* for now */
90           .st_value = 0x0,
91           .st_other = ELF_ST_VIS(STV_DEFAULT),
92           .st_size  = 0,
93         },
94         { .st_name  = 1, /* index in sym_string table */
95           .st_info  = ELF_ST_BIND(STB_LOCAL) | ELF_ST_TYPE(STT_FUNC),
96           .st_shndx = 1,
97           .st_value = 0, /* for now */
98           .st_other = ELF_ST_VIS(STV_DEFAULT),
99           .st_size  = 0, /* for now */
100         }
101 };
102
103 #ifdef BUILD_ID_URANDOM
104 static void
105 gen_build_id(struct buildid_note *note,
106              unsigned long load_addr __maybe_unused,
107              const void *code __maybe_unused,
108              size_t csize __maybe_unused)
109 {
110         int fd;
111         size_t sz = sizeof(note->build_id);
112         ssize_t sret;
113
114         fd = open("/dev/urandom", O_RDONLY);
115         if (fd == -1)
116                 err(1, "cannot access /dev/urandom for buildid");
117
118         sret = read(fd, note->build_id, sz);
119
120         close(fd);
121
122         if (sret != (ssize_t)sz)
123                 memset(note->build_id, 0, sz);
124 }
125 #endif
126
127 #ifdef BUILD_ID_SHA
128 static void
129 gen_build_id(struct buildid_note *note,
130              unsigned long load_addr __maybe_unused,
131              const void *code,
132              size_t csize)
133 {
134         if (sizeof(note->build_id) < SHA_DIGEST_LENGTH)
135                 errx(1, "build_id too small for SHA1");
136
137         SHA1(code, csize, (unsigned char *)note->build_id);
138 }
139 #endif
140
141 #ifdef BUILD_ID_MD5
142 static void
143 gen_build_id(struct buildid_note *note, unsigned long load_addr, const void *code, size_t csize)
144 {
145         MD5_CTX context;
146
147         if (sizeof(note->build_id) < 16)
148                 errx(1, "build_id too small for MD5");
149
150         MD5_Init(&context);
151         MD5_Update(&context, &load_addr, sizeof(load_addr));
152         MD5_Update(&context, code, csize);
153         MD5_Final((unsigned char *)note->build_id, &context);
154 }
155 #endif
156
157 static int
158 jit_add_eh_frame_info(Elf *e, void* unwinding, uint64_t unwinding_header_size,
159                       uint64_t unwinding_size, uint64_t base_offset)
160 {
161         Elf_Data *d;
162         Elf_Scn *scn;
163         Elf_Shdr *shdr;
164         uint64_t unwinding_table_size = unwinding_size - unwinding_header_size;
165
166         /*
167          * setup eh_frame section
168          */
169         scn = elf_newscn(e);
170         if (!scn) {
171                 warnx("cannot create section");
172                 return -1;
173         }
174
175         d = elf_newdata(scn);
176         if (!d) {
177                 warnx("cannot get new data");
178                 return -1;
179         }
180
181         d->d_align = 8;
182         d->d_off = 0LL;
183         d->d_buf = unwinding;
184         d->d_type = ELF_T_BYTE;
185         d->d_size = unwinding_table_size;
186         d->d_version = EV_CURRENT;
187
188         shdr = elf_getshdr(scn);
189         if (!shdr) {
190                 warnx("cannot get section header");
191                 return -1;
192         }
193
194         shdr->sh_name = 104;
195         shdr->sh_type = SHT_PROGBITS;
196         shdr->sh_addr = base_offset;
197         shdr->sh_flags = SHF_ALLOC;
198         shdr->sh_entsize = 0;
199
200         /*
201          * setup eh_frame_hdr section
202          */
203         scn = elf_newscn(e);
204         if (!scn) {
205                 warnx("cannot create section");
206                 return -1;
207         }
208
209         d = elf_newdata(scn);
210         if (!d) {
211                 warnx("cannot get new data");
212                 return -1;
213         }
214
215         d->d_align = 4;
216         d->d_off = 0LL;
217         d->d_buf = unwinding + unwinding_table_size;
218         d->d_type = ELF_T_BYTE;
219         d->d_size = unwinding_header_size;
220         d->d_version = EV_CURRENT;
221
222         shdr = elf_getshdr(scn);
223         if (!shdr) {
224                 warnx("cannot get section header");
225                 return -1;
226         }
227
228         shdr->sh_name = 90;
229         shdr->sh_type = SHT_PROGBITS;
230         shdr->sh_addr = base_offset + unwinding_table_size;
231         shdr->sh_flags = SHF_ALLOC;
232         shdr->sh_entsize = 0;
233
234         return 0;
235 }
236
237 /*
238  * fd: file descriptor open for writing for the output file
239  * load_addr: code load address (could be zero, just used for buildid)
240  * sym: function name (for native code - used as the symbol)
241  * code: the native code
242  * csize: the code size in bytes
243  */
244 int
245 jit_write_elf(int fd, uint64_t load_addr, const char *sym,
246               const void *code, int csize,
247               void *debug __maybe_unused, int nr_debug_entries __maybe_unused,
248               void *unwinding, uint64_t unwinding_header_size, uint64_t unwinding_size)
249 {
250         Elf *e;
251         Elf_Data *d;
252         Elf_Scn *scn;
253         Elf_Ehdr *ehdr;
254         Elf_Shdr *shdr;
255         uint64_t eh_frame_base_offset;
256         char *strsym = NULL;
257         int symlen;
258         int retval = -1;
259
260         if (elf_version(EV_CURRENT) == EV_NONE) {
261                 warnx("ELF initialization failed");
262                 return -1;
263         }
264
265         e = elf_begin(fd, ELF_C_WRITE, NULL);
266         if (!e) {
267                 warnx("elf_begin failed");
268                 goto error;
269         }
270
271         /*
272          * setup ELF header
273          */
274         ehdr = elf_newehdr(e);
275         if (!ehdr) {
276                 warnx("cannot get ehdr");
277                 goto error;
278         }
279
280         ehdr->e_ident[EI_DATA] = GEN_ELF_ENDIAN;
281         ehdr->e_ident[EI_CLASS] = GEN_ELF_CLASS;
282         ehdr->e_machine = GEN_ELF_ARCH;
283         ehdr->e_type = ET_DYN;
284         ehdr->e_entry = GEN_ELF_TEXT_OFFSET;
285         ehdr->e_version = EV_CURRENT;
286         ehdr->e_shstrndx= unwinding ? 4 : 2; /* shdr index for section name */
287
288         /*
289          * setup text section
290          */
291         scn = elf_newscn(e);
292         if (!scn) {
293                 warnx("cannot create section");
294                 goto error;
295         }
296
297         d = elf_newdata(scn);
298         if (!d) {
299                 warnx("cannot get new data");
300                 goto error;
301         }
302
303         d->d_align = 16;
304         d->d_off = 0LL;
305         d->d_buf = (void *)code;
306         d->d_type = ELF_T_BYTE;
307         d->d_size = csize;
308         d->d_version = EV_CURRENT;
309
310         shdr = elf_getshdr(scn);
311         if (!shdr) {
312                 warnx("cannot get section header");
313                 goto error;
314         }
315
316         shdr->sh_name = 1;
317         shdr->sh_type = SHT_PROGBITS;
318         shdr->sh_addr = GEN_ELF_TEXT_OFFSET;
319         shdr->sh_flags = SHF_EXECINSTR | SHF_ALLOC;
320         shdr->sh_entsize = 0;
321
322         /*
323          * Setup .eh_frame_hdr and .eh_frame
324          */
325         if (unwinding) {
326                 eh_frame_base_offset = ALIGN_8(GEN_ELF_TEXT_OFFSET + csize);
327                 retval = jit_add_eh_frame_info(e, unwinding,
328                                                unwinding_header_size, unwinding_size,
329                                                eh_frame_base_offset);
330                 if (retval)
331                         goto error;
332         }
333
334         /*
335          * setup section headers string table
336          */
337         scn = elf_newscn(e);
338         if (!scn) {
339                 warnx("cannot create section");
340                 goto error;
341         }
342
343         d = elf_newdata(scn);
344         if (!d) {
345                 warnx("cannot get new data");
346                 goto error;
347         }
348
349         d->d_align = 1;
350         d->d_off = 0LL;
351         d->d_buf = shd_string_table;
352         d->d_type = ELF_T_BYTE;
353         d->d_size = sizeof(shd_string_table);
354         d->d_version = EV_CURRENT;
355
356         shdr = elf_getshdr(scn);
357         if (!shdr) {
358                 warnx("cannot get section header");
359                 goto error;
360         }
361
362         shdr->sh_name = 7; /* offset of '.shstrtab' in shd_string_table */
363         shdr->sh_type = SHT_STRTAB;
364         shdr->sh_flags = 0;
365         shdr->sh_entsize = 0;
366
367         /*
368          * setup symtab section
369          */
370         symtab[1].st_size  = csize;
371         symtab[1].st_value = GEN_ELF_TEXT_OFFSET;
372
373         scn = elf_newscn(e);
374         if (!scn) {
375                 warnx("cannot create section");
376                 goto error;
377         }
378
379         d = elf_newdata(scn);
380         if (!d) {
381                 warnx("cannot get new data");
382                 goto error;
383         }
384
385         d->d_align = 8;
386         d->d_off = 0LL;
387         d->d_buf = symtab;
388         d->d_type = ELF_T_SYM;
389         d->d_size = sizeof(symtab);
390         d->d_version = EV_CURRENT;
391
392         shdr = elf_getshdr(scn);
393         if (!shdr) {
394                 warnx("cannot get section header");
395                 goto error;
396         }
397
398         shdr->sh_name = 17; /* offset of '.symtab' in shd_string_table */
399         shdr->sh_type = SHT_SYMTAB;
400         shdr->sh_flags = 0;
401         shdr->sh_entsize = sizeof(Elf_Sym);
402         shdr->sh_link = unwinding ? 6 : 4; /* index of .strtab section */
403
404         /*
405          * setup symbols string table
406          * 2 = 1 for 0 in 1st entry, 1 for the 0 at end of symbol for 2nd entry
407          */
408         symlen = 2 + strlen(sym);
409         strsym = calloc(1, symlen);
410         if (!strsym) {
411                 warnx("cannot allocate strsym");
412                 goto error;
413         }
414         strcpy(strsym + 1, sym);
415
416         scn = elf_newscn(e);
417         if (!scn) {
418                 warnx("cannot create section");
419                 goto error;
420         }
421
422         d = elf_newdata(scn);
423         if (!d) {
424                 warnx("cannot get new data");
425                 goto error;
426         }
427
428         d->d_align = 1;
429         d->d_off = 0LL;
430         d->d_buf = strsym;
431         d->d_type = ELF_T_BYTE;
432         d->d_size = symlen;
433         d->d_version = EV_CURRENT;
434
435         shdr = elf_getshdr(scn);
436         if (!shdr) {
437                 warnx("cannot get section header");
438                 goto error;
439         }
440
441         shdr->sh_name = 25; /* offset in shd_string_table */
442         shdr->sh_type = SHT_STRTAB;
443         shdr->sh_flags = 0;
444         shdr->sh_entsize = 0;
445
446         /*
447          * setup build-id section
448          */
449         scn = elf_newscn(e);
450         if (!scn) {
451                 warnx("cannot create section");
452                 goto error;
453         }
454
455         d = elf_newdata(scn);
456         if (!d) {
457                 warnx("cannot get new data");
458                 goto error;
459         }
460
461         /*
462          * build-id generation
463          */
464         gen_build_id(&bnote, load_addr, code, csize);
465         bnote.desc.namesz = sizeof(bnote.name); /* must include 0 termination */
466         bnote.desc.descsz = sizeof(bnote.build_id);
467         bnote.desc.type   = NT_GNU_BUILD_ID;
468         strcpy(bnote.name, "GNU");
469
470         d->d_align = 4;
471         d->d_off = 0LL;
472         d->d_buf = &bnote;
473         d->d_type = ELF_T_BYTE;
474         d->d_size = sizeof(bnote);
475         d->d_version = EV_CURRENT;
476
477         shdr = elf_getshdr(scn);
478         if (!shdr) {
479                 warnx("cannot get section header");
480                 goto error;
481         }
482
483         shdr->sh_name = 33; /* offset in shd_string_table */
484         shdr->sh_type = SHT_NOTE;
485         shdr->sh_addr = 0x0;
486         shdr->sh_flags = SHF_ALLOC;
487         shdr->sh_size = sizeof(bnote);
488         shdr->sh_entsize = 0;
489
490 #ifdef HAVE_DWARF_SUPPORT
491         if (debug && nr_debug_entries) {
492                 retval = jit_add_debug_info(e, load_addr, debug, nr_debug_entries);
493                 if (retval)
494                         goto error;
495         } else
496 #endif
497         {
498                 if (elf_update(e, ELF_C_WRITE) < 0) {
499                         warnx("elf_update 4 failed");
500                         goto error;
501                 }
502         }
503
504         retval = 0;
505 error:
506         (void)elf_end(e);
507
508         free(strsym);
509
510
511         return retval;
512 }
513
514 #ifndef JVMTI
515
516 static unsigned char x86_code[] = {
517     0xBB, 0x2A, 0x00, 0x00, 0x00, /* movl $42, %ebx */
518     0xB8, 0x01, 0x00, 0x00, 0x00, /* movl $1, %eax */
519     0xCD, 0x80            /* int $0x80 */
520 };
521
522 static struct options options;
523
524 int main(int argc, char **argv)
525 {
526         int c, fd, ret;
527
528         while ((c = getopt(argc, argv, "o:h")) != -1) {
529                 switch (c) {
530                 case 'o':
531                         options.output = optarg;
532                         break;
533                 case 'h':
534                         printf("Usage: genelf -o output_file [-h]\n");
535                         return 0;
536                 default:
537                         errx(1, "unknown option");
538                 }
539         }
540
541         fd = open(options.output, O_CREAT|O_TRUNC|O_RDWR, 0666);
542         if (fd == -1)
543                 err(1, "cannot create file %s", options.output);
544
545         ret = jit_write_elf(fd, "main", x86_code, sizeof(x86_code));
546         close(fd);
547
548         if (ret != 0)
549                 unlink(options.output);
550
551         return ret;
552 }
553 #endif