xref: /OK3568_Linux_fs/kernel/tools/perf/util/genelf.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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