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