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