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