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