xref: /aosp_15_r20/external/elfutils/libasm/asm_end.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
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