1*7304104dSAndroid Build Coastguard Worker /* Finalize operations on the assembler context, free all resources.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2002, 2003, 2005, 2016 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker Written by Ulrich Drepper <[email protected]>, 2002.
5*7304104dSAndroid Build Coastguard Worker
6*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
7*7304104dSAndroid Build Coastguard Worker it under the terms of either
8*7304104dSAndroid Build Coastguard Worker
9*7304104dSAndroid Build Coastguard Worker * the GNU Lesser General Public License as published by the Free
10*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 3 of the License, or (at
11*7304104dSAndroid Build Coastguard Worker your option) any later version
12*7304104dSAndroid Build Coastguard Worker
13*7304104dSAndroid Build Coastguard Worker or
14*7304104dSAndroid Build Coastguard Worker
15*7304104dSAndroid Build Coastguard Worker * the GNU General Public License as published by the Free
16*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 2 of the License, or (at
17*7304104dSAndroid Build Coastguard Worker your option) any later version
18*7304104dSAndroid Build Coastguard Worker
19*7304104dSAndroid Build Coastguard Worker or both in parallel, as here.
20*7304104dSAndroid Build Coastguard Worker
21*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
22*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
23*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24*7304104dSAndroid Build Coastguard Worker General Public License for more details.
25*7304104dSAndroid Build Coastguard Worker
26*7304104dSAndroid Build Coastguard Worker You should have received copies of the GNU General Public License and
27*7304104dSAndroid Build Coastguard Worker the GNU Lesser General Public License along with this program. If
28*7304104dSAndroid Build Coastguard Worker not, see <http://www.gnu.org/licenses/>. */
29*7304104dSAndroid Build Coastguard Worker
30*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
31*7304104dSAndroid Build Coastguard Worker # include <config.h>
32*7304104dSAndroid Build Coastguard Worker #endif
33*7304104dSAndroid Build Coastguard Worker
34*7304104dSAndroid Build Coastguard Worker #include <assert.h>
35*7304104dSAndroid Build Coastguard Worker #include <stdio.h>
36*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
37*7304104dSAndroid Build Coastguard Worker #include <string.h>
38*7304104dSAndroid Build Coastguard Worker #include <sys/stat.h>
39*7304104dSAndroid Build Coastguard Worker
40*7304104dSAndroid Build Coastguard Worker #include <libasmP.h>
41*7304104dSAndroid Build Coastguard Worker #include <libelf.h>
42*7304104dSAndroid Build Coastguard Worker
43*7304104dSAndroid Build Coastguard Worker
44*7304104dSAndroid Build Coastguard Worker static int
text_end(AsmCtx_t * ctx)45*7304104dSAndroid Build Coastguard Worker text_end (AsmCtx_t *ctx __attribute__ ((unused)))
46*7304104dSAndroid Build Coastguard Worker {
47*7304104dSAndroid Build Coastguard Worker if (fflush (ctx->out.file) != 0)
48*7304104dSAndroid Build Coastguard Worker {
49*7304104dSAndroid Build Coastguard Worker __libasm_seterrno (ASM_E_IOERROR);
50*7304104dSAndroid Build Coastguard Worker return -1;
51*7304104dSAndroid Build Coastguard Worker }
52*7304104dSAndroid Build Coastguard Worker
53*7304104dSAndroid Build Coastguard Worker return 0;
54*7304104dSAndroid Build Coastguard Worker }
55*7304104dSAndroid Build Coastguard Worker
56*7304104dSAndroid Build Coastguard Worker
57*7304104dSAndroid Build Coastguard Worker static int
binary_end(AsmCtx_t * ctx)58*7304104dSAndroid Build Coastguard Worker binary_end (AsmCtx_t *ctx)
59*7304104dSAndroid Build Coastguard Worker {
60*7304104dSAndroid Build Coastguard Worker void *symtab = NULL;
61*7304104dSAndroid Build Coastguard Worker Dwelf_Strent *symscn_strent = NULL;
62*7304104dSAndroid Build Coastguard Worker Dwelf_Strent *strscn_strent = NULL;
63*7304104dSAndroid Build Coastguard Worker Dwelf_Strent *xndxscn_strent = NULL;
64*7304104dSAndroid Build Coastguard Worker Elf_Scn *shstrscn;
65*7304104dSAndroid Build Coastguard Worker Dwelf_Strent *shstrscn_strent;
66*7304104dSAndroid Build Coastguard Worker size_t shstrscnndx;
67*7304104dSAndroid Build Coastguard Worker size_t symscnndx = 0;
68*7304104dSAndroid Build Coastguard Worker size_t strscnndx = 0;
69*7304104dSAndroid Build Coastguard Worker size_t xndxscnndx = 0;
70*7304104dSAndroid Build Coastguard Worker Elf_Data *data;
71*7304104dSAndroid Build Coastguard Worker Elf_Data *shstrtabdata;
72*7304104dSAndroid Build Coastguard Worker Elf_Data *strtabdata = NULL;
73*7304104dSAndroid Build Coastguard Worker Elf_Data *xndxdata = NULL;
74*7304104dSAndroid Build Coastguard Worker GElf_Shdr shdr_mem;
75*7304104dSAndroid Build Coastguard Worker GElf_Shdr *shdr;
76*7304104dSAndroid Build Coastguard Worker GElf_Ehdr ehdr_mem;
77*7304104dSAndroid Build Coastguard Worker GElf_Ehdr *ehdr;
78*7304104dSAndroid Build Coastguard Worker AsmScn_t *asmscn;
79*7304104dSAndroid Build Coastguard Worker int result = 0;
80*7304104dSAndroid Build Coastguard Worker
81*7304104dSAndroid Build Coastguard Worker /* Iterate over the created sections and compute the offsets of the
82*7304104dSAndroid Build Coastguard Worker various subsections and fill in the content. */
83*7304104dSAndroid Build Coastguard Worker for (asmscn = ctx->section_list; asmscn != NULL; asmscn = asmscn->allnext)
84*7304104dSAndroid Build Coastguard Worker {
85*7304104dSAndroid Build Coastguard Worker #if 0
86*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn = elf_getscn (ctx->out.elf, asmscn->data.main.scnndx);
87*7304104dSAndroid Build Coastguard Worker #else
88*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn = asmscn->data.main.scn;
89*7304104dSAndroid Build Coastguard Worker #endif
90*7304104dSAndroid Build Coastguard Worker off_t offset = 0;
91*7304104dSAndroid Build Coastguard Worker AsmScn_t *asmsubscn = asmscn;
92*7304104dSAndroid Build Coastguard Worker
93*7304104dSAndroid Build Coastguard Worker do
94*7304104dSAndroid Build Coastguard Worker {
95*7304104dSAndroid Build Coastguard Worker struct AsmData *content = asmsubscn->content;
96*7304104dSAndroid Build Coastguard Worker bool first = true;
97*7304104dSAndroid Build Coastguard Worker
98*7304104dSAndroid Build Coastguard Worker offset = ((offset + asmsubscn->max_align - 1)
99*7304104dSAndroid Build Coastguard Worker & ~(asmsubscn->max_align - 1));
100*7304104dSAndroid Build Coastguard Worker
101*7304104dSAndroid Build Coastguard Worker /* Update the offset for this subsection. This field now
102*7304104dSAndroid Build Coastguard Worker stores the offset of the first by in this subsection. */
103*7304104dSAndroid Build Coastguard Worker asmsubscn->offset = offset;
104*7304104dSAndroid Build Coastguard Worker
105*7304104dSAndroid Build Coastguard Worker /* Note that the content list is circular. */
106*7304104dSAndroid Build Coastguard Worker if (content != NULL)
107*7304104dSAndroid Build Coastguard Worker do
108*7304104dSAndroid Build Coastguard Worker {
109*7304104dSAndroid Build Coastguard Worker Elf_Data *newdata = elf_newdata (scn);
110*7304104dSAndroid Build Coastguard Worker
111*7304104dSAndroid Build Coastguard Worker if (newdata == NULL)
112*7304104dSAndroid Build Coastguard Worker {
113*7304104dSAndroid Build Coastguard Worker __libasm_seterrno (ASM_E_LIBELF);
114*7304104dSAndroid Build Coastguard Worker return -1;
115*7304104dSAndroid Build Coastguard Worker }
116*7304104dSAndroid Build Coastguard Worker
117*7304104dSAndroid Build Coastguard Worker newdata->d_buf = content->data;
118*7304104dSAndroid Build Coastguard Worker newdata->d_type = ELF_T_BYTE;
119*7304104dSAndroid Build Coastguard Worker newdata->d_size = content->len;
120*7304104dSAndroid Build Coastguard Worker newdata->d_off = offset;
121*7304104dSAndroid Build Coastguard Worker newdata->d_align = first ? asmsubscn->max_align : 1;
122*7304104dSAndroid Build Coastguard Worker
123*7304104dSAndroid Build Coastguard Worker offset += content->len;
124*7304104dSAndroid Build Coastguard Worker }
125*7304104dSAndroid Build Coastguard Worker while ((content = content->next) != asmsubscn->content);
126*7304104dSAndroid Build Coastguard Worker }
127*7304104dSAndroid Build Coastguard Worker while ((asmsubscn = asmsubscn->subnext) != NULL);
128*7304104dSAndroid Build Coastguard Worker }
129*7304104dSAndroid Build Coastguard Worker
130*7304104dSAndroid Build Coastguard Worker
131*7304104dSAndroid Build Coastguard Worker /* Create the symbol table if necessary. */
132*7304104dSAndroid Build Coastguard Worker if (ctx->nsymbol_tab > 0)
133*7304104dSAndroid Build Coastguard Worker {
134*7304104dSAndroid Build Coastguard Worker /* Create the symbol table and string table section names. */
135*7304104dSAndroid Build Coastguard Worker symscn_strent = dwelf_strtab_add_len (ctx->section_strtab, ".symtab", 8);
136*7304104dSAndroid Build Coastguard Worker strscn_strent = dwelf_strtab_add_len (ctx->section_strtab, ".strtab", 8);
137*7304104dSAndroid Build Coastguard Worker
138*7304104dSAndroid Build Coastguard Worker /* Create the symbol string table section. */
139*7304104dSAndroid Build Coastguard Worker Elf_Scn *strscn = elf_newscn (ctx->out.elf);
140*7304104dSAndroid Build Coastguard Worker strtabdata = elf_newdata (strscn);
141*7304104dSAndroid Build Coastguard Worker shdr = gelf_getshdr (strscn, &shdr_mem);
142*7304104dSAndroid Build Coastguard Worker if (strtabdata == NULL || shdr == NULL)
143*7304104dSAndroid Build Coastguard Worker {
144*7304104dSAndroid Build Coastguard Worker __libasm_seterrno (ASM_E_LIBELF);
145*7304104dSAndroid Build Coastguard Worker return -1;
146*7304104dSAndroid Build Coastguard Worker }
147*7304104dSAndroid Build Coastguard Worker strscnndx = elf_ndxscn (strscn);
148*7304104dSAndroid Build Coastguard Worker
149*7304104dSAndroid Build Coastguard Worker dwelf_strtab_finalize (ctx->symbol_strtab, strtabdata);
150*7304104dSAndroid Build Coastguard Worker
151*7304104dSAndroid Build Coastguard Worker shdr->sh_type = SHT_STRTAB;
152*7304104dSAndroid Build Coastguard Worker assert (shdr->sh_entsize == 0);
153*7304104dSAndroid Build Coastguard Worker
154*7304104dSAndroid Build Coastguard Worker (void) gelf_update_shdr (strscn, shdr);
155*7304104dSAndroid Build Coastguard Worker
156*7304104dSAndroid Build Coastguard Worker /* Create the symbol table section. */
157*7304104dSAndroid Build Coastguard Worker Elf_Scn *symscn = elf_newscn (ctx->out.elf);
158*7304104dSAndroid Build Coastguard Worker data = elf_newdata (symscn);
159*7304104dSAndroid Build Coastguard Worker shdr = gelf_getshdr (symscn, &shdr_mem);
160*7304104dSAndroid Build Coastguard Worker if (data == NULL || shdr == NULL)
161*7304104dSAndroid Build Coastguard Worker {
162*7304104dSAndroid Build Coastguard Worker __libasm_seterrno (ASM_E_LIBELF);
163*7304104dSAndroid Build Coastguard Worker return -1;
164*7304104dSAndroid Build Coastguard Worker }
165*7304104dSAndroid Build Coastguard Worker symscnndx = elf_ndxscn (symscn);
166*7304104dSAndroid Build Coastguard Worker
167*7304104dSAndroid Build Coastguard Worker /* We know how many symbols there will be in the symbol table. */
168*7304104dSAndroid Build Coastguard Worker data->d_size = gelf_fsize (ctx->out.elf, ELF_T_SYM,
169*7304104dSAndroid Build Coastguard Worker ctx->nsymbol_tab + 1, EV_CURRENT);
170*7304104dSAndroid Build Coastguard Worker symtab = malloc (data->d_size);
171*7304104dSAndroid Build Coastguard Worker if (symtab == NULL)
172*7304104dSAndroid Build Coastguard Worker return -1;
173*7304104dSAndroid Build Coastguard Worker data->d_buf = symtab;
174*7304104dSAndroid Build Coastguard Worker data->d_type = ELF_T_SYM;
175*7304104dSAndroid Build Coastguard Worker data->d_off = 0;
176*7304104dSAndroid Build Coastguard Worker
177*7304104dSAndroid Build Coastguard Worker /* Clear the first entry. */
178*7304104dSAndroid Build Coastguard Worker GElf_Sym syment;
179*7304104dSAndroid Build Coastguard Worker memset (&syment, '\0', sizeof (syment));
180*7304104dSAndroid Build Coastguard Worker (void) gelf_update_sym (data, 0, &syment);
181*7304104dSAndroid Build Coastguard Worker
182*7304104dSAndroid Build Coastguard Worker /* Iterate over the symbol table. */
183*7304104dSAndroid Build Coastguard Worker void *runp = NULL;
184*7304104dSAndroid Build Coastguard Worker int ptr_local = 1; /* Start with index 1; zero remains unused. */
185*7304104dSAndroid Build Coastguard Worker int ptr_nonlocal = ctx->nsymbol_tab;
186*7304104dSAndroid Build Coastguard Worker uint32_t *xshndx = NULL;
187*7304104dSAndroid Build Coastguard Worker AsmSym_t *sym;
188*7304104dSAndroid Build Coastguard Worker while ((sym = asm_symbol_tab_iterate (&ctx->symbol_tab, &runp)) != NULL)
189*7304104dSAndroid Build Coastguard Worker if (asm_emit_symbol_p (dwelf_strent_str (sym->strent)))
190*7304104dSAndroid Build Coastguard Worker {
191*7304104dSAndroid Build Coastguard Worker assert (ptr_local <= ptr_nonlocal);
192*7304104dSAndroid Build Coastguard Worker
193*7304104dSAndroid Build Coastguard Worker syment.st_name = dwelf_strent_off (sym->strent);
194*7304104dSAndroid Build Coastguard Worker syment.st_info = GELF_ST_INFO (sym->binding, sym->type);
195*7304104dSAndroid Build Coastguard Worker syment.st_other = 0;
196*7304104dSAndroid Build Coastguard Worker syment.st_value = sym->scn->offset + sym->offset;
197*7304104dSAndroid Build Coastguard Worker syment.st_size = sym->size;
198*7304104dSAndroid Build Coastguard Worker
199*7304104dSAndroid Build Coastguard Worker /* Add local symbols at the beginning, the other from
200*7304104dSAndroid Build Coastguard Worker the end. */
201*7304104dSAndroid Build Coastguard Worker int ptr = sym->binding == STB_LOCAL ? ptr_local++ : ptr_nonlocal--;
202*7304104dSAndroid Build Coastguard Worker
203*7304104dSAndroid Build Coastguard Worker /* Determine the section index. We have to handle the
204*7304104dSAndroid Build Coastguard Worker overflow correctly. */
205*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn = (sym->scn->subsection_id == 0
206*7304104dSAndroid Build Coastguard Worker ? sym->scn->data.main.scn
207*7304104dSAndroid Build Coastguard Worker : sym->scn->data.up->data.main.scn);
208*7304104dSAndroid Build Coastguard Worker
209*7304104dSAndroid Build Coastguard Worker Elf32_Word ndx;
210*7304104dSAndroid Build Coastguard Worker if (unlikely (scn == ASM_ABS_SCN))
211*7304104dSAndroid Build Coastguard Worker ndx = SHN_ABS;
212*7304104dSAndroid Build Coastguard Worker else if (unlikely (scn == ASM_COM_SCN))
213*7304104dSAndroid Build Coastguard Worker ndx = SHN_COMMON;
214*7304104dSAndroid Build Coastguard Worker else if (unlikely ((ndx = elf_ndxscn (scn)) >= SHN_LORESERVE))
215*7304104dSAndroid Build Coastguard Worker {
216*7304104dSAndroid Build Coastguard Worker if (unlikely (xshndx == NULL))
217*7304104dSAndroid Build Coastguard Worker {
218*7304104dSAndroid Build Coastguard Worker /* The extended section index section does not yet
219*7304104dSAndroid Build Coastguard Worker exist. */
220*7304104dSAndroid Build Coastguard Worker Elf_Scn *xndxscn;
221*7304104dSAndroid Build Coastguard Worker
222*7304104dSAndroid Build Coastguard Worker xndxscn = elf_newscn (ctx->out.elf);
223*7304104dSAndroid Build Coastguard Worker xndxdata = elf_newdata (xndxscn);
224*7304104dSAndroid Build Coastguard Worker shdr = gelf_getshdr (xndxscn, &shdr_mem);
225*7304104dSAndroid Build Coastguard Worker if (xndxdata == NULL || shdr == NULL)
226*7304104dSAndroid Build Coastguard Worker {
227*7304104dSAndroid Build Coastguard Worker __libasm_seterrno (ASM_E_LIBELF);
228*7304104dSAndroid Build Coastguard Worker return -1;
229*7304104dSAndroid Build Coastguard Worker }
230*7304104dSAndroid Build Coastguard Worker xndxscnndx = elf_ndxscn (xndxscn);
231*7304104dSAndroid Build Coastguard Worker
232*7304104dSAndroid Build Coastguard Worker shdr->sh_type = SHT_SYMTAB_SHNDX;
233*7304104dSAndroid Build Coastguard Worker shdr->sh_entsize = sizeof (Elf32_Word);
234*7304104dSAndroid Build Coastguard Worker shdr->sh_addralign = sizeof (Elf32_Word);
235*7304104dSAndroid Build Coastguard Worker shdr->sh_link = symscnndx;
236*7304104dSAndroid Build Coastguard Worker
237*7304104dSAndroid Build Coastguard Worker (void) gelf_update_shdr (xndxscn, shdr);
238*7304104dSAndroid Build Coastguard Worker
239*7304104dSAndroid Build Coastguard Worker xndxscn_strent = dwelf_strtab_add_len (ctx->section_strtab,
240*7304104dSAndroid Build Coastguard Worker ".symtab_shndx",
241*7304104dSAndroid Build Coastguard Worker 14);
242*7304104dSAndroid Build Coastguard Worker
243*7304104dSAndroid Build Coastguard Worker /* Note that using 'elf32_fsize' instead of
244*7304104dSAndroid Build Coastguard Worker 'gelf_fsize' here is correct. */
245*7304104dSAndroid Build Coastguard Worker xndxdata->d_size = elf32_fsize (ELF_T_WORD,
246*7304104dSAndroid Build Coastguard Worker ctx->nsymbol_tab + 1,
247*7304104dSAndroid Build Coastguard Worker EV_CURRENT);
248*7304104dSAndroid Build Coastguard Worker xshndx = xndxdata->d_buf = calloc (1, xndxdata->d_size);
249*7304104dSAndroid Build Coastguard Worker if (xshndx == NULL)
250*7304104dSAndroid Build Coastguard Worker return -1;
251*7304104dSAndroid Build Coastguard Worker /* Using ELF_T_WORD here relies on the fact that the
252*7304104dSAndroid Build Coastguard Worker 32- and 64-bit types are the same size. */
253*7304104dSAndroid Build Coastguard Worker xndxdata->d_type = ELF_T_WORD;
254*7304104dSAndroid Build Coastguard Worker xndxdata->d_off = 0;
255*7304104dSAndroid Build Coastguard Worker }
256*7304104dSAndroid Build Coastguard Worker
257*7304104dSAndroid Build Coastguard Worker /* Store the real section index in the extended section
258*7304104dSAndroid Build Coastguard Worker index table. */
259*7304104dSAndroid Build Coastguard Worker assert ((size_t) ptr < ctx->nsymbol_tab + 1);
260*7304104dSAndroid Build Coastguard Worker xshndx[ptr] = ndx;
261*7304104dSAndroid Build Coastguard Worker
262*7304104dSAndroid Build Coastguard Worker /* And signal that this happened. */
263*7304104dSAndroid Build Coastguard Worker ndx = SHN_XINDEX;
264*7304104dSAndroid Build Coastguard Worker }
265*7304104dSAndroid Build Coastguard Worker syment.st_shndx = ndx;
266*7304104dSAndroid Build Coastguard Worker
267*7304104dSAndroid Build Coastguard Worker /* Remember where we put the symbol. */
268*7304104dSAndroid Build Coastguard Worker sym->symidx = ptr;
269*7304104dSAndroid Build Coastguard Worker
270*7304104dSAndroid Build Coastguard Worker (void) gelf_update_sym (data, ptr, &syment);
271*7304104dSAndroid Build Coastguard Worker }
272*7304104dSAndroid Build Coastguard Worker
273*7304104dSAndroid Build Coastguard Worker assert (ptr_local == ptr_nonlocal + 1);
274*7304104dSAndroid Build Coastguard Worker
275*7304104dSAndroid Build Coastguard Worker shdr->sh_type = SHT_SYMTAB;
276*7304104dSAndroid Build Coastguard Worker shdr->sh_link = strscnndx;
277*7304104dSAndroid Build Coastguard Worker shdr->sh_info = ptr_local;
278*7304104dSAndroid Build Coastguard Worker shdr->sh_entsize = gelf_fsize (ctx->out.elf, ELF_T_SYM, 1, EV_CURRENT);
279*7304104dSAndroid Build Coastguard Worker shdr->sh_addralign = gelf_fsize (ctx->out.elf, ELF_T_ADDR, 1,
280*7304104dSAndroid Build Coastguard Worker EV_CURRENT);
281*7304104dSAndroid Build Coastguard Worker
282*7304104dSAndroid Build Coastguard Worker (void) gelf_update_shdr (symscn, shdr);
283*7304104dSAndroid Build Coastguard Worker }
284*7304104dSAndroid Build Coastguard Worker
285*7304104dSAndroid Build Coastguard Worker
286*7304104dSAndroid Build Coastguard Worker /* Create the section header string table section and fill in the
287*7304104dSAndroid Build Coastguard Worker references in the section headers. */
288*7304104dSAndroid Build Coastguard Worker shstrscn = elf_newscn (ctx->out.elf);
289*7304104dSAndroid Build Coastguard Worker shstrtabdata = elf_newdata (shstrscn);
290*7304104dSAndroid Build Coastguard Worker shdr = gelf_getshdr (shstrscn, &shdr_mem);
291*7304104dSAndroid Build Coastguard Worker if (shstrscn == NULL || shstrtabdata == NULL || shdr == NULL)
292*7304104dSAndroid Build Coastguard Worker {
293*7304104dSAndroid Build Coastguard Worker __libasm_seterrno (ASM_E_LIBELF);
294*7304104dSAndroid Build Coastguard Worker return -1;
295*7304104dSAndroid Build Coastguard Worker }
296*7304104dSAndroid Build Coastguard Worker
297*7304104dSAndroid Build Coastguard Worker
298*7304104dSAndroid Build Coastguard Worker /* Add the name of the section header string table. */
299*7304104dSAndroid Build Coastguard Worker shstrscn_strent = dwelf_strtab_add_len (ctx->section_strtab,
300*7304104dSAndroid Build Coastguard Worker ".shstrtab", 10);
301*7304104dSAndroid Build Coastguard Worker
302*7304104dSAndroid Build Coastguard Worker dwelf_strtab_finalize (ctx->section_strtab, shstrtabdata);
303*7304104dSAndroid Build Coastguard Worker
304*7304104dSAndroid Build Coastguard Worker shdr->sh_type = SHT_STRTAB;
305*7304104dSAndroid Build Coastguard Worker assert (shdr->sh_entsize == 0);
306*7304104dSAndroid Build Coastguard Worker shdr->sh_name = dwelf_strent_off (shstrscn_strent);
307*7304104dSAndroid Build Coastguard Worker
308*7304104dSAndroid Build Coastguard Worker (void) gelf_update_shdr (shstrscn, shdr);
309*7304104dSAndroid Build Coastguard Worker
310*7304104dSAndroid Build Coastguard Worker
311*7304104dSAndroid Build Coastguard Worker /* Create the section groups. */
312*7304104dSAndroid Build Coastguard Worker if (ctx->groups != NULL)
313*7304104dSAndroid Build Coastguard Worker {
314*7304104dSAndroid Build Coastguard Worker AsmScnGrp_t *runp = ctx->groups->next;
315*7304104dSAndroid Build Coastguard Worker
316*7304104dSAndroid Build Coastguard Worker do
317*7304104dSAndroid Build Coastguard Worker {
318*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn;
319*7304104dSAndroid Build Coastguard Worker Elf32_Word *grpdata;
320*7304104dSAndroid Build Coastguard Worker
321*7304104dSAndroid Build Coastguard Worker scn = runp->scn;
322*7304104dSAndroid Build Coastguard Worker assert (scn != NULL);
323*7304104dSAndroid Build Coastguard Worker shdr = gelf_getshdr (scn, &shdr_mem);
324*7304104dSAndroid Build Coastguard Worker assert (shdr != NULL);
325*7304104dSAndroid Build Coastguard Worker
326*7304104dSAndroid Build Coastguard Worker data = elf_newdata (scn);
327*7304104dSAndroid Build Coastguard Worker if (data == NULL)
328*7304104dSAndroid Build Coastguard Worker {
329*7304104dSAndroid Build Coastguard Worker __libasm_seterrno (ASM_E_LIBELF);
330*7304104dSAndroid Build Coastguard Worker return -1;
331*7304104dSAndroid Build Coastguard Worker }
332*7304104dSAndroid Build Coastguard Worker
333*7304104dSAndroid Build Coastguard Worker /* It is correct to use 'elf32_fsize' instead of 'gelf_fsize'
334*7304104dSAndroid Build Coastguard Worker here. */
335*7304104dSAndroid Build Coastguard Worker data->d_size = elf32_fsize (ELF_T_WORD, runp->nmembers + 1,
336*7304104dSAndroid Build Coastguard Worker EV_CURRENT);
337*7304104dSAndroid Build Coastguard Worker grpdata = data->d_buf = malloc (data->d_size);
338*7304104dSAndroid Build Coastguard Worker if (grpdata == NULL)
339*7304104dSAndroid Build Coastguard Worker return -1;
340*7304104dSAndroid Build Coastguard Worker data->d_type = ELF_T_WORD;
341*7304104dSAndroid Build Coastguard Worker data->d_off = 0;
342*7304104dSAndroid Build Coastguard Worker data->d_align = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
343*7304104dSAndroid Build Coastguard Worker
344*7304104dSAndroid Build Coastguard Worker /* The first word of the section is filled with the flag word. */
345*7304104dSAndroid Build Coastguard Worker *grpdata++ = runp->flags;
346*7304104dSAndroid Build Coastguard Worker
347*7304104dSAndroid Build Coastguard Worker if (runp->members != NULL)
348*7304104dSAndroid Build Coastguard Worker {
349*7304104dSAndroid Build Coastguard Worker AsmScn_t *member = runp->members->data.main.next_in_group;
350*7304104dSAndroid Build Coastguard Worker
351*7304104dSAndroid Build Coastguard Worker do
352*7304104dSAndroid Build Coastguard Worker {
353*7304104dSAndroid Build Coastguard Worker /* Only sections, not subsections, can be registered
354*7304104dSAndroid Build Coastguard Worker as member of a group. The subsections get
355*7304104dSAndroid Build Coastguard Worker automatically included. */
356*7304104dSAndroid Build Coastguard Worker assert (member->subsection_id == 0);
357*7304104dSAndroid Build Coastguard Worker
358*7304104dSAndroid Build Coastguard Worker *grpdata++ = elf_ndxscn (member->data.main.scn);
359*7304104dSAndroid Build Coastguard Worker }
360*7304104dSAndroid Build Coastguard Worker while ((member = member->data.main.next_in_group)
361*7304104dSAndroid Build Coastguard Worker != runp->members->data.main.next_in_group);
362*7304104dSAndroid Build Coastguard Worker }
363*7304104dSAndroid Build Coastguard Worker
364*7304104dSAndroid Build Coastguard Worker /* Construct the section header. */
365*7304104dSAndroid Build Coastguard Worker shdr->sh_name = dwelf_strent_off (runp->strent);
366*7304104dSAndroid Build Coastguard Worker shdr->sh_type = SHT_GROUP;
367*7304104dSAndroid Build Coastguard Worker shdr->sh_flags = 0;
368*7304104dSAndroid Build Coastguard Worker shdr->sh_link = symscnndx;
369*7304104dSAndroid Build Coastguard Worker /* If the user did not specify a signature we use the initial
370*7304104dSAndroid Build Coastguard Worker empty symbol in the symbol table as the signature. */
371*7304104dSAndroid Build Coastguard Worker shdr->sh_info = (runp->signature != NULL
372*7304104dSAndroid Build Coastguard Worker ? runp->signature->symidx : 0);
373*7304104dSAndroid Build Coastguard Worker
374*7304104dSAndroid Build Coastguard Worker (void) gelf_update_shdr (scn, shdr);
375*7304104dSAndroid Build Coastguard Worker }
376*7304104dSAndroid Build Coastguard Worker while ((runp = runp->next) != ctx->groups->next);
377*7304104dSAndroid Build Coastguard Worker }
378*7304104dSAndroid Build Coastguard Worker
379*7304104dSAndroid Build Coastguard Worker
380*7304104dSAndroid Build Coastguard Worker /* Add the name to the symbol section. */
381*7304104dSAndroid Build Coastguard Worker if (likely (symscnndx != 0))
382*7304104dSAndroid Build Coastguard Worker {
383*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn = elf_getscn (ctx->out.elf, symscnndx);
384*7304104dSAndroid Build Coastguard Worker
385*7304104dSAndroid Build Coastguard Worker shdr = gelf_getshdr (scn, &shdr_mem);
386*7304104dSAndroid Build Coastguard Worker
387*7304104dSAndroid Build Coastguard Worker shdr->sh_name = dwelf_strent_off (symscn_strent);
388*7304104dSAndroid Build Coastguard Worker
389*7304104dSAndroid Build Coastguard Worker (void) gelf_update_shdr (scn, shdr);
390*7304104dSAndroid Build Coastguard Worker
391*7304104dSAndroid Build Coastguard Worker
392*7304104dSAndroid Build Coastguard Worker /* Add the name to the string section. */
393*7304104dSAndroid Build Coastguard Worker assert (strscnndx != 0);
394*7304104dSAndroid Build Coastguard Worker scn = elf_getscn (ctx->out.elf, strscnndx);
395*7304104dSAndroid Build Coastguard Worker
396*7304104dSAndroid Build Coastguard Worker shdr = gelf_getshdr (scn, &shdr_mem);
397*7304104dSAndroid Build Coastguard Worker
398*7304104dSAndroid Build Coastguard Worker shdr->sh_name = dwelf_strent_off (strscn_strent);
399*7304104dSAndroid Build Coastguard Worker
400*7304104dSAndroid Build Coastguard Worker (void) gelf_update_shdr (scn, shdr);
401*7304104dSAndroid Build Coastguard Worker
402*7304104dSAndroid Build Coastguard Worker
403*7304104dSAndroid Build Coastguard Worker /* Add the name to the extended symbol index section. */
404*7304104dSAndroid Build Coastguard Worker if (xndxscnndx != 0)
405*7304104dSAndroid Build Coastguard Worker {
406*7304104dSAndroid Build Coastguard Worker scn = elf_getscn (ctx->out.elf, xndxscnndx);
407*7304104dSAndroid Build Coastguard Worker
408*7304104dSAndroid Build Coastguard Worker shdr = gelf_getshdr (scn, &shdr_mem);
409*7304104dSAndroid Build Coastguard Worker
410*7304104dSAndroid Build Coastguard Worker shdr->sh_name = dwelf_strent_off (xndxscn_strent);
411*7304104dSAndroid Build Coastguard Worker
412*7304104dSAndroid Build Coastguard Worker (void) gelf_update_shdr (scn, shdr);
413*7304104dSAndroid Build Coastguard Worker }
414*7304104dSAndroid Build Coastguard Worker }
415*7304104dSAndroid Build Coastguard Worker
416*7304104dSAndroid Build Coastguard Worker
417*7304104dSAndroid Build Coastguard Worker /* Iterate over the created sections and fill in the names. */
418*7304104dSAndroid Build Coastguard Worker for (asmscn = ctx->section_list; asmscn != NULL; asmscn = asmscn->allnext)
419*7304104dSAndroid Build Coastguard Worker {
420*7304104dSAndroid Build Coastguard Worker shdr = gelf_getshdr (asmscn->data.main.scn, &shdr_mem);
421*7304104dSAndroid Build Coastguard Worker /* This better should not fail. */
422*7304104dSAndroid Build Coastguard Worker assert (shdr != NULL);
423*7304104dSAndroid Build Coastguard Worker
424*7304104dSAndroid Build Coastguard Worker shdr->sh_name = dwelf_strent_off (asmscn->data.main.strent);
425*7304104dSAndroid Build Coastguard Worker
426*7304104dSAndroid Build Coastguard Worker /* We now know the maximum alignment. */
427*7304104dSAndroid Build Coastguard Worker shdr->sh_addralign = asmscn->max_align;
428*7304104dSAndroid Build Coastguard Worker
429*7304104dSAndroid Build Coastguard Worker (void) gelf_update_shdr (asmscn->data.main.scn, shdr);
430*7304104dSAndroid Build Coastguard Worker }
431*7304104dSAndroid Build Coastguard Worker
432*7304104dSAndroid Build Coastguard Worker /* Put the reference to the section header string table in the ELF
433*7304104dSAndroid Build Coastguard Worker header. */
434*7304104dSAndroid Build Coastguard Worker ehdr = gelf_getehdr (ctx->out.elf, &ehdr_mem);
435*7304104dSAndroid Build Coastguard Worker assert (ehdr != NULL);
436*7304104dSAndroid Build Coastguard Worker
437*7304104dSAndroid Build Coastguard Worker shstrscnndx = elf_ndxscn (shstrscn);
438*7304104dSAndroid Build Coastguard Worker if (unlikely (shstrscnndx > SHN_HIRESERVE)
439*7304104dSAndroid Build Coastguard Worker || unlikely (shstrscnndx == SHN_XINDEX))
440*7304104dSAndroid Build Coastguard Worker {
441*7304104dSAndroid Build Coastguard Worker /* The index of the section header string sectio is too large. */
442*7304104dSAndroid Build Coastguard Worker Elf_Scn *scn = elf_getscn (ctx->out.elf, 0);
443*7304104dSAndroid Build Coastguard Worker
444*7304104dSAndroid Build Coastguard Worker /* Get the header for the zeroth section. */
445*7304104dSAndroid Build Coastguard Worker shdr = gelf_getshdr (scn, &shdr_mem);
446*7304104dSAndroid Build Coastguard Worker /* This better does not fail. */
447*7304104dSAndroid Build Coastguard Worker assert (shdr != NULL);
448*7304104dSAndroid Build Coastguard Worker
449*7304104dSAndroid Build Coastguard Worker /* The sh_link field of the zeroth section header contains the value. */
450*7304104dSAndroid Build Coastguard Worker shdr->sh_link = shstrscnndx;
451*7304104dSAndroid Build Coastguard Worker
452*7304104dSAndroid Build Coastguard Worker (void) gelf_update_shdr (scn, shdr);
453*7304104dSAndroid Build Coastguard Worker
454*7304104dSAndroid Build Coastguard Worker /* This is the sign for the overflow. */
455*7304104dSAndroid Build Coastguard Worker ehdr->e_shstrndx = SHN_XINDEX;
456*7304104dSAndroid Build Coastguard Worker }
457*7304104dSAndroid Build Coastguard Worker else
458*7304104dSAndroid Build Coastguard Worker ehdr->e_shstrndx = elf_ndxscn (shstrscn);
459*7304104dSAndroid Build Coastguard Worker
460*7304104dSAndroid Build Coastguard Worker if (unlikely (gelf_update_ehdr (ctx->out.elf, ehdr) == 0))
461*7304104dSAndroid Build Coastguard Worker {
462*7304104dSAndroid Build Coastguard Worker __libasm_seterrno (ASM_E_LIBELF);
463*7304104dSAndroid Build Coastguard Worker result = -1;
464*7304104dSAndroid Build Coastguard Worker }
465*7304104dSAndroid Build Coastguard Worker
466*7304104dSAndroid Build Coastguard Worker /* Write out the ELF file. */
467*7304104dSAndroid Build Coastguard Worker if (unlikely (elf_update (ctx->out.elf, ELF_C_WRITE_MMAP) < 0))
468*7304104dSAndroid Build Coastguard Worker {
469*7304104dSAndroid Build Coastguard Worker __libasm_seterrno (ASM_E_LIBELF);
470*7304104dSAndroid Build Coastguard Worker result = -1;
471*7304104dSAndroid Build Coastguard Worker }
472*7304104dSAndroid Build Coastguard Worker
473*7304104dSAndroid Build Coastguard Worker /* We do not need the section header and symbol string tables anymore. */
474*7304104dSAndroid Build Coastguard Worker free (shstrtabdata->d_buf);
475*7304104dSAndroid Build Coastguard Worker if (strtabdata != NULL)
476*7304104dSAndroid Build Coastguard Worker free (strtabdata->d_buf);
477*7304104dSAndroid Build Coastguard Worker /* We might have allocated the extended symbol table index. */
478*7304104dSAndroid Build Coastguard Worker if (xndxdata != NULL)
479*7304104dSAndroid Build Coastguard Worker free (xndxdata->d_buf);
480*7304104dSAndroid Build Coastguard Worker
481*7304104dSAndroid Build Coastguard Worker /* Free section groups memory. */
482*7304104dSAndroid Build Coastguard Worker AsmScnGrp_t *scngrp = ctx->groups;
483*7304104dSAndroid Build Coastguard Worker if (scngrp != NULL)
484*7304104dSAndroid Build Coastguard Worker do
485*7304104dSAndroid Build Coastguard Worker free (elf_getdata (scngrp->scn, NULL)->d_buf);
486*7304104dSAndroid Build Coastguard Worker while ((scngrp = scngrp->next) != ctx->groups);
487*7304104dSAndroid Build Coastguard Worker
488*7304104dSAndroid Build Coastguard Worker /* Finalize the ELF handling. */
489*7304104dSAndroid Build Coastguard Worker if (unlikely (elf_end (ctx->out.elf)) != 0)
490*7304104dSAndroid Build Coastguard Worker {
491*7304104dSAndroid Build Coastguard Worker __libasm_seterrno (ASM_E_LIBELF);
492*7304104dSAndroid Build Coastguard Worker result = -1;
493*7304104dSAndroid Build Coastguard Worker }
494*7304104dSAndroid Build Coastguard Worker
495*7304104dSAndroid Build Coastguard Worker /* Free the temporary resources. */
496*7304104dSAndroid Build Coastguard Worker free (symtab);
497*7304104dSAndroid Build Coastguard Worker
498*7304104dSAndroid Build Coastguard Worker return result;
499*7304104dSAndroid Build Coastguard Worker }
500*7304104dSAndroid Build Coastguard Worker
501*7304104dSAndroid Build Coastguard Worker
502*7304104dSAndroid Build Coastguard Worker int
asm_end(AsmCtx_t * ctx)503*7304104dSAndroid Build Coastguard Worker asm_end (AsmCtx_t *ctx)
504*7304104dSAndroid Build Coastguard Worker {
505*7304104dSAndroid Build Coastguard Worker int result;
506*7304104dSAndroid Build Coastguard Worker
507*7304104dSAndroid Build Coastguard Worker if (ctx == NULL)
508*7304104dSAndroid Build Coastguard Worker /* Something went wrong earlier. */
509*7304104dSAndroid Build Coastguard Worker return -1;
510*7304104dSAndroid Build Coastguard Worker
511*7304104dSAndroid Build Coastguard Worker result = unlikely (ctx->textp) ? text_end (ctx) : binary_end (ctx);
512*7304104dSAndroid Build Coastguard Worker if (result != 0)
513*7304104dSAndroid Build Coastguard Worker return result;
514*7304104dSAndroid Build Coastguard Worker
515*7304104dSAndroid Build Coastguard Worker /* Make the new file globally readable and user/group-writable. */
516*7304104dSAndroid Build Coastguard Worker if (fchmod (ctx->fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) != 0)
517*7304104dSAndroid Build Coastguard Worker {
518*7304104dSAndroid Build Coastguard Worker __libasm_seterrno (ASM_E_CANNOT_CHMOD);
519*7304104dSAndroid Build Coastguard Worker return -1;
520*7304104dSAndroid Build Coastguard Worker }
521*7304104dSAndroid Build Coastguard Worker
522*7304104dSAndroid Build Coastguard Worker /* Rename output file. */
523*7304104dSAndroid Build Coastguard Worker if (rename (ctx->tmp_fname, ctx->fname) != 0)
524*7304104dSAndroid Build Coastguard Worker {
525*7304104dSAndroid Build Coastguard Worker __libasm_seterrno (ASM_E_CANNOT_RENAME);
526*7304104dSAndroid Build Coastguard Worker return -1;
527*7304104dSAndroid Build Coastguard Worker }
528*7304104dSAndroid Build Coastguard Worker
529*7304104dSAndroid Build Coastguard Worker /* Free the resources. */
530*7304104dSAndroid Build Coastguard Worker __libasm_finictx (ctx);
531*7304104dSAndroid Build Coastguard Worker
532*7304104dSAndroid Build Coastguard Worker return 0;
533*7304104dSAndroid Build Coastguard Worker }
534*7304104dSAndroid Build Coastguard Worker
535*7304104dSAndroid Build Coastguard Worker
536*7304104dSAndroid Build Coastguard Worker static void
free_section(AsmScn_t * scnp)537*7304104dSAndroid Build Coastguard Worker free_section (AsmScn_t *scnp)
538*7304104dSAndroid Build Coastguard Worker {
539*7304104dSAndroid Build Coastguard Worker void *oldp;
540*7304104dSAndroid Build Coastguard Worker
541*7304104dSAndroid Build Coastguard Worker if (scnp->subnext != NULL)
542*7304104dSAndroid Build Coastguard Worker free_section (scnp->subnext);
543*7304104dSAndroid Build Coastguard Worker
544*7304104dSAndroid Build Coastguard Worker /* This is a circular single linked list. */
545*7304104dSAndroid Build Coastguard Worker struct AsmData *data = scnp->content;
546*7304104dSAndroid Build Coastguard Worker if (data != NULL)
547*7304104dSAndroid Build Coastguard Worker {
548*7304104dSAndroid Build Coastguard Worker while (data != scnp->content)
549*7304104dSAndroid Build Coastguard Worker {
550*7304104dSAndroid Build Coastguard Worker oldp = data;
551*7304104dSAndroid Build Coastguard Worker data = data->next;
552*7304104dSAndroid Build Coastguard Worker free (oldp);
553*7304104dSAndroid Build Coastguard Worker }
554*7304104dSAndroid Build Coastguard Worker free (scnp->content);
555*7304104dSAndroid Build Coastguard Worker }
556*7304104dSAndroid Build Coastguard Worker free (scnp);
557*7304104dSAndroid Build Coastguard Worker }
558*7304104dSAndroid Build Coastguard Worker
559*7304104dSAndroid Build Coastguard Worker
560*7304104dSAndroid Build Coastguard Worker void
561*7304104dSAndroid Build Coastguard Worker internal_function
__libasm_finictx(AsmCtx_t * ctx)562*7304104dSAndroid Build Coastguard Worker __libasm_finictx (AsmCtx_t *ctx)
563*7304104dSAndroid Build Coastguard Worker {
564*7304104dSAndroid Build Coastguard Worker /* Iterate through section table and free individual entries. */
565*7304104dSAndroid Build Coastguard Worker AsmScn_t *scn = ctx->section_list;
566*7304104dSAndroid Build Coastguard Worker while (scn != NULL)
567*7304104dSAndroid Build Coastguard Worker {
568*7304104dSAndroid Build Coastguard Worker AsmScn_t *oldp = scn;
569*7304104dSAndroid Build Coastguard Worker scn = scn->allnext;
570*7304104dSAndroid Build Coastguard Worker free_section (oldp);
571*7304104dSAndroid Build Coastguard Worker }
572*7304104dSAndroid Build Coastguard Worker
573*7304104dSAndroid Build Coastguard Worker /* Free the resources of the symbol table. */
574*7304104dSAndroid Build Coastguard Worker void *runp = NULL;
575*7304104dSAndroid Build Coastguard Worker AsmSym_t *sym;
576*7304104dSAndroid Build Coastguard Worker while ((sym = asm_symbol_tab_iterate (&ctx->symbol_tab, &runp)) != NULL)
577*7304104dSAndroid Build Coastguard Worker free (sym);
578*7304104dSAndroid Build Coastguard Worker asm_symbol_tab_free (&ctx->symbol_tab);
579*7304104dSAndroid Build Coastguard Worker
580*7304104dSAndroid Build Coastguard Worker
581*7304104dSAndroid Build Coastguard Worker /* Free section groups. */
582*7304104dSAndroid Build Coastguard Worker AsmScnGrp_t *scngrp = ctx->groups;
583*7304104dSAndroid Build Coastguard Worker if (scngrp != NULL)
584*7304104dSAndroid Build Coastguard Worker do
585*7304104dSAndroid Build Coastguard Worker {
586*7304104dSAndroid Build Coastguard Worker AsmScnGrp_t *oldp = scngrp;
587*7304104dSAndroid Build Coastguard Worker
588*7304104dSAndroid Build Coastguard Worker scngrp = scngrp->next;
589*7304104dSAndroid Build Coastguard Worker free (oldp);
590*7304104dSAndroid Build Coastguard Worker }
591*7304104dSAndroid Build Coastguard Worker while (scngrp != ctx->groups);
592*7304104dSAndroid Build Coastguard Worker
593*7304104dSAndroid Build Coastguard Worker
594*7304104dSAndroid Build Coastguard Worker if (unlikely (ctx->textp))
595*7304104dSAndroid Build Coastguard Worker {
596*7304104dSAndroid Build Coastguard Worker /* Close the stream. */
597*7304104dSAndroid Build Coastguard Worker fclose (ctx->out.file);
598*7304104dSAndroid Build Coastguard Worker }
599*7304104dSAndroid Build Coastguard Worker else
600*7304104dSAndroid Build Coastguard Worker {
601*7304104dSAndroid Build Coastguard Worker /* Close the output file. */
602*7304104dSAndroid Build Coastguard Worker /* XXX We should test for errors here but what would we do if we'd
603*7304104dSAndroid Build Coastguard Worker find any. */
604*7304104dSAndroid Build Coastguard Worker (void) close (ctx->fd);
605*7304104dSAndroid Build Coastguard Worker
606*7304104dSAndroid Build Coastguard Worker /* And the string tables. */
607*7304104dSAndroid Build Coastguard Worker dwelf_strtab_free (ctx->section_strtab);
608*7304104dSAndroid Build Coastguard Worker dwelf_strtab_free (ctx->symbol_strtab);
609*7304104dSAndroid Build Coastguard Worker }
610*7304104dSAndroid Build Coastguard Worker
611*7304104dSAndroid Build Coastguard Worker /* Initialize the lock. */
612*7304104dSAndroid Build Coastguard Worker rwlock_fini (ctx->lock);
613*7304104dSAndroid Build Coastguard Worker
614*7304104dSAndroid Build Coastguard Worker /* Finally free the data structure. */
615*7304104dSAndroid Build Coastguard Worker free (ctx);
616*7304104dSAndroid Build Coastguard Worker }
617