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.
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
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
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
19 or both in parallel, as here.
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.
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/>. */
48 text_end (AsmCtx_t *ctx __attribute__ ((unused)))
50 if (fclose (ctx->out.file) != 0)
52 __libasm_seterrno (ASM_E_IOERROR);
61 binary_end (AsmCtx_t *ctx)
64 Dwelf_Strent *symscn_strent = NULL;
65 Dwelf_Strent *strscn_strent = NULL;
66 Dwelf_Strent *xndxscn_strent = NULL;
68 Dwelf_Strent *shstrscn_strent;
72 size_t xndxscnndx = 0;
74 Elf_Data *shstrtabdata;
75 Elf_Data *strtabdata = NULL;
76 Elf_Data *xndxdata = NULL;
84 /* Iterate over the created sections and compute the offsets of the
85 various subsections and fill in the content. */
86 for (asmscn = ctx->section_list; asmscn != NULL; asmscn = asmscn->allnext)
89 Elf_Scn *scn = elf_getscn (ctx->out.elf, asmscn->data.main.scnndx);
91 Elf_Scn *scn = asmscn->data.main.scn;
94 AsmScn_t *asmsubscn = asmscn;
98 struct AsmData *content = asmsubscn->content;
101 offset = ((offset + asmsubscn->max_align - 1)
102 & ~(asmsubscn->max_align - 1));
104 /* Update the offset for this subsection. This field now
105 stores the offset of the first by in this subsection. */
106 asmsubscn->offset = offset;
108 /* Note that the content list is circular. */
112 Elf_Data *newdata = elf_newdata (scn);
116 __libasm_seterrno (ASM_E_LIBELF);
120 newdata->d_buf = content->data;
121 newdata->d_type = ELF_T_BYTE;
122 newdata->d_size = content->len;
123 newdata->d_off = offset;
124 newdata->d_align = first ? asmsubscn->max_align : 1;
126 offset += content->len;
128 while ((content = content->next) != asmsubscn->content);
130 while ((asmsubscn = asmsubscn->subnext) != NULL);
134 /* Create the symbol table if necessary. */
135 if (ctx->nsymbol_tab > 0)
137 /* Create the symbol table and string table section names. */
138 symscn_strent = dwelf_strtab_add_len (ctx->section_strtab, ".symtab", 8);
139 strscn_strent = dwelf_strtab_add_len (ctx->section_strtab, ".strtab", 8);
141 /* Create the symbol string table section. */
142 Elf_Scn *strscn = elf_newscn (ctx->out.elf);
143 strtabdata = elf_newdata (strscn);
144 shdr = gelf_getshdr (strscn, &shdr_mem);
145 if (strtabdata == NULL || shdr == NULL)
147 __libasm_seterrno (ASM_E_LIBELF);
150 strscnndx = elf_ndxscn (strscn);
152 dwelf_strtab_finalize (ctx->symbol_strtab, strtabdata);
154 shdr->sh_type = SHT_STRTAB;
155 assert (shdr->sh_entsize == 0);
157 (void) gelf_update_shdr (strscn, shdr);
159 /* Create the symbol table section. */
160 Elf_Scn *symscn = elf_newscn (ctx->out.elf);
161 data = elf_newdata (symscn);
162 shdr = gelf_getshdr (symscn, &shdr_mem);
163 if (data == NULL || shdr == NULL)
165 __libasm_seterrno (ASM_E_LIBELF);
168 symscnndx = elf_ndxscn (symscn);
170 /* We know how many symbols there will be in the symbol table. */
171 data->d_size = gelf_fsize (ctx->out.elf, ELF_T_SYM,
172 ctx->nsymbol_tab + 1, EV_CURRENT);
173 symtab = malloc (data->d_size);
176 data->d_buf = symtab;
177 data->d_type = ELF_T_SYM;
180 /* Clear the first entry. */
182 memset (&syment, '\0', sizeof (syment));
183 (void) gelf_update_sym (data, 0, &syment);
185 /* Iterate over the symbol table. */
187 int ptr_local = 1; /* Start with index 1; zero remains unused. */
188 int ptr_nonlocal = ctx->nsymbol_tab;
189 uint32_t *xshndx = NULL;
191 while ((sym = asm_symbol_tab_iterate (&ctx->symbol_tab, &runp)) != NULL)
192 if (asm_emit_symbol_p (dwelf_strent_str (sym->strent)))
194 assert (ptr_local <= ptr_nonlocal);
196 syment.st_name = dwelf_strent_off (sym->strent);
197 syment.st_info = GELF_ST_INFO (sym->binding, sym->type);
199 syment.st_value = sym->scn->offset + sym->offset;
200 syment.st_size = sym->size;
202 /* Add local symbols at the beginning, the other from
204 int ptr = sym->binding == STB_LOCAL ? ptr_local++ : ptr_nonlocal--;
206 /* Determine the section index. We have to handle the
207 overflow correctly. */
208 Elf_Scn *scn = (sym->scn->subsection_id == 0
209 ? sym->scn->data.main.scn
210 : sym->scn->data.up->data.main.scn);
213 if (unlikely (scn == ASM_ABS_SCN))
215 else if (unlikely (scn == ASM_COM_SCN))
217 else if (unlikely ((ndx = elf_ndxscn (scn)) >= SHN_LORESERVE))
219 if (unlikely (xshndx == NULL))
221 /* The extended section index section does not yet
225 xndxscn = elf_newscn (ctx->out.elf);
226 xndxdata = elf_newdata (xndxscn);
227 shdr = gelf_getshdr (xndxscn, &shdr_mem);
228 if (xndxdata == NULL || shdr == NULL)
230 __libasm_seterrno (ASM_E_LIBELF);
233 xndxscnndx = elf_ndxscn (xndxscn);
235 shdr->sh_type = SHT_SYMTAB_SHNDX;
236 shdr->sh_entsize = sizeof (Elf32_Word);
237 shdr->sh_addralign = sizeof (Elf32_Word);
238 shdr->sh_link = symscnndx;
240 (void) gelf_update_shdr (xndxscn, shdr);
242 xndxscn_strent = dwelf_strtab_add_len (ctx->section_strtab,
246 /* Note that using 'elf32_fsize' instead of
247 'gelf_fsize' here is correct. */
248 xndxdata->d_size = elf32_fsize (ELF_T_WORD,
249 ctx->nsymbol_tab + 1,
251 xshndx = xndxdata->d_buf = calloc (1, xndxdata->d_size);
254 /* Using ELF_T_WORD here relies on the fact that the
255 32- and 64-bit types are the same size. */
256 xndxdata->d_type = ELF_T_WORD;
260 /* Store the real section index in the extended setion
262 assert ((size_t) ptr < ctx->nsymbol_tab + 1);
265 /* And signal that this happened. */
268 syment.st_shndx = ndx;
270 /* Remember where we put the symbol. */
273 (void) gelf_update_sym (data, ptr, &syment);
276 assert (ptr_local == ptr_nonlocal + 1);
278 shdr->sh_type = SHT_SYMTAB;
279 shdr->sh_link = strscnndx;
280 shdr->sh_info = ptr_local;
281 shdr->sh_entsize = gelf_fsize (ctx->out.elf, ELF_T_SYM, 1, EV_CURRENT);
282 shdr->sh_addralign = gelf_fsize (ctx->out.elf, ELF_T_ADDR, 1,
285 (void) gelf_update_shdr (symscn, shdr);
289 /* Create the section header string table section and fill in the
290 references in the section headers. */
291 shstrscn = elf_newscn (ctx->out.elf);
292 shstrtabdata = elf_newdata (shstrscn);
293 shdr = gelf_getshdr (shstrscn, &shdr_mem);
294 if (shstrscn == NULL || shstrtabdata == NULL || shdr == NULL)
296 __libasm_seterrno (ASM_E_LIBELF);
301 /* Add the name of the section header string table. */
302 shstrscn_strent = dwelf_strtab_add_len (ctx->section_strtab,
305 dwelf_strtab_finalize (ctx->section_strtab, shstrtabdata);
307 shdr->sh_type = SHT_STRTAB;
308 assert (shdr->sh_entsize == 0);
309 shdr->sh_name = dwelf_strent_off (shstrscn_strent);
311 (void) gelf_update_shdr (shstrscn, shdr);
314 /* Create the section groups. */
315 if (ctx->groups != NULL)
317 AsmScnGrp_t *runp = ctx->groups->next;
325 assert (scn != NULL);
326 shdr = gelf_getshdr (scn, &shdr_mem);
327 assert (shdr != NULL);
329 data = elf_newdata (scn);
332 __libasm_seterrno (ASM_E_LIBELF);
336 /* It is correct to use 'elf32_fsize' instead of 'gelf_fsize'
338 data->d_size = elf32_fsize (ELF_T_WORD, runp->nmembers + 1,
340 grpdata = data->d_buf = malloc (data->d_size);
343 data->d_type = ELF_T_WORD;
345 data->d_align = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
347 /* The first word of the section is filled with the flag word. */
348 *grpdata++ = runp->flags;
350 if (runp->members != NULL)
352 AsmScn_t *member = runp->members->data.main.next_in_group;
356 /* Only sections, not subsections, can be registered
357 as member of a group. The subsections get
358 automatically included. */
359 assert (member->subsection_id == 0);
361 *grpdata++ = elf_ndxscn (member->data.main.scn);
363 while ((member = member->data.main.next_in_group)
364 != runp->members->data.main.next_in_group);
367 /* Construct the section header. */
368 shdr->sh_name = dwelf_strent_off (runp->strent);
369 shdr->sh_type = SHT_GROUP;
371 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 shdr->sh_info = (runp->signature != NULL
375 ? runp->signature->symidx : 0);
377 (void) gelf_update_shdr (scn, shdr);
379 while ((runp = runp->next) != ctx->groups->next);
383 /* Add the name to the symbol section. */
384 if (likely (symscnndx != 0))
386 Elf_Scn *scn = elf_getscn (ctx->out.elf, symscnndx);
388 shdr = gelf_getshdr (scn, &shdr_mem);
390 shdr->sh_name = dwelf_strent_off (symscn_strent);
392 (void) gelf_update_shdr (scn, shdr);
395 /* Add the name to the string section. */
396 assert (strscnndx != 0);
397 scn = elf_getscn (ctx->out.elf, strscnndx);
399 shdr = gelf_getshdr (scn, &shdr_mem);
401 shdr->sh_name = dwelf_strent_off (strscn_strent);
403 (void) gelf_update_shdr (scn, shdr);
406 /* Add the name to the extended symbol index section. */
409 scn = elf_getscn (ctx->out.elf, xndxscnndx);
411 shdr = gelf_getshdr (scn, &shdr_mem);
413 shdr->sh_name = dwelf_strent_off (xndxscn_strent);
415 (void) gelf_update_shdr (scn, shdr);
420 /* Iterate over the created sections and fill in the names. */
421 for (asmscn = ctx->section_list; asmscn != NULL; asmscn = asmscn->allnext)
423 shdr = gelf_getshdr (asmscn->data.main.scn, &shdr_mem);
424 /* This better should not fail. */
425 assert (shdr != NULL);
427 shdr->sh_name = dwelf_strent_off (asmscn->data.main.strent);
429 /* We now know the maximum alignment. */
430 shdr->sh_addralign = asmscn->max_align;
432 (void) gelf_update_shdr (asmscn->data.main.scn, shdr);
435 /* Put the reference to the section header string table in the ELF
437 ehdr = gelf_getehdr (ctx->out.elf, &ehdr_mem);
438 assert (ehdr != NULL);
440 shstrscnndx = elf_ndxscn (shstrscn);
441 if (unlikely (shstrscnndx > SHN_HIRESERVE)
442 || unlikely (shstrscnndx == SHN_XINDEX))
444 /* The index of the section header string sectio is too large. */
445 Elf_Scn *scn = elf_getscn (ctx->out.elf, 0);
447 /* Get the header for the zeroth section. */
448 shdr = gelf_getshdr (scn, &shdr_mem);
449 /* This better does not fail. */
450 assert (shdr != NULL);
452 /* The sh_link field of the zeroth section header contains the value. */
453 shdr->sh_link = shstrscnndx;
455 (void) gelf_update_shdr (scn, shdr);
457 /* This is the sign for the overflow. */
458 ehdr->e_shstrndx = SHN_XINDEX;
461 ehdr->e_shstrndx = elf_ndxscn (shstrscn);
463 gelf_update_ehdr (ctx->out.elf, ehdr);
465 /* Write out the ELF file. */
466 if (unlikely (elf_update (ctx->out.elf, ELF_C_WRITE_MMAP) < 0))
468 __libasm_seterrno (ASM_E_LIBELF);
472 /* We do not need the section header and symbol string tables anymore. */
473 free (shstrtabdata->d_buf);
474 if (strtabdata != NULL)
475 free (strtabdata->d_buf);
476 /* We might have allocated the extended symbol table index. */
477 if (xndxdata != NULL)
478 free (xndxdata->d_buf);
480 /* Free section groups memory. */
481 AsmScnGrp_t *scngrp = ctx->groups;
484 free (elf_getdata (scngrp->scn, NULL)->d_buf);
485 while ((scngrp = scngrp->next) != ctx->groups);
487 /* Finalize the ELF handling. */
488 if (unlikely (elf_end (ctx->out.elf)) != 0)
490 __libasm_seterrno (ASM_E_LIBELF);
494 /* Free the temporary resources. */
502 asm_end (AsmCtx_t *ctx)
507 /* Something went wrong earlier. */
510 result = unlikely (ctx->textp) ? text_end (ctx) : binary_end (ctx);
514 /* Make the new file globally readable and user/group-writable. */
515 if (fchmod (ctx->fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) != 0)
517 __libasm_seterrno (ASM_E_CANNOT_CHMOD);
521 /* Rename output file. */
522 if (rename (ctx->tmp_fname, ctx->fname) != 0)
524 __libasm_seterrno (ASM_E_CANNOT_RENAME);
528 /* Free the resources. */
529 __libasm_finictx (ctx);
536 free_section (AsmScn_t *scnp)
540 if (scnp->subnext != NULL)
541 free_section (scnp->subnext);
543 struct AsmData *data = scnp->content;
551 while (oldp != scnp->content);
559 __libasm_finictx (AsmCtx_t *ctx)
561 /* Iterate through section table and free individual entries. */
562 AsmScn_t *scn = ctx->section_list;
565 AsmScn_t *oldp = scn;
570 /* Free the resources of the symbol table. */
573 while ((sym = asm_symbol_tab_iterate (&ctx->symbol_tab, &runp)) != NULL)
575 asm_symbol_tab_free (&ctx->symbol_tab);
578 /* Free section groups. */
579 AsmScnGrp_t *scngrp = ctx->groups;
583 AsmScnGrp_t *oldp = scngrp;
585 scngrp = scngrp->next;
588 while (scngrp != ctx->groups);
591 if (unlikely (ctx->textp))
593 /* Close the stream. */
594 fclose (ctx->out.file);
598 /* Close the output file. */
599 /* XXX We should test for errors here but what would we do if we'd
601 (void) close (ctx->fd);
603 /* And the string tables. */
604 dwelf_strtab_free (ctx->section_strtab);
605 dwelf_strtab_free (ctx->symbol_strtab);
608 /* Initialize the lock. */
609 rwlock_fini (ctx->lock);
611 /* Finally free the data structure. */