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