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.
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/>. */
49 text_end (AsmCtx_t *ctx __attribute__ ((unused)))
51 if (fclose (ctx->out.file) != 0)
53 __libasm_seterrno (ASM_E_IOERROR);
62 binary_end (AsmCtx_t *ctx)
65 struct Ebl_Strent *symscn_strent = NULL;
66 struct Ebl_Strent *strscn_strent = NULL;
67 struct Ebl_Strent *xndxscn_strent = NULL;
69 struct Ebl_Strent *shstrscn_strent;
73 size_t xndxscnndx = 0;
75 Elf_Data *shstrtabdata;
76 Elf_Data *strtabdata = NULL;
77 Elf_Data *xndxdata = NULL;
85 /* Iterate over the created sections and compute the offsets of the
86 various subsections and fill in the content. */
87 for (asmscn = ctx->section_list; asmscn != NULL; asmscn = asmscn->allnext)
90 Elf_Scn *scn = elf_getscn (ctx->out.elf, asmscn->data.main.scnndx);
92 Elf_Scn *scn = asmscn->data.main.scn;
95 AsmScn_t *asmsubscn = asmscn;
99 struct AsmData *content = asmsubscn->content;
102 offset = ((offset + asmsubscn->max_align - 1)
103 & ~(asmsubscn->max_align - 1));
105 /* Update the offset for this subsection. This field now
106 stores the offset of the first by in this subsection. */
107 asmsubscn->offset = offset;
109 /* Note that the content list is circular. */
113 Elf_Data *newdata = elf_newdata (scn);
117 __libasm_seterrno (ASM_E_LIBELF);
121 newdata->d_buf = content->data;
122 newdata->d_type = ELF_T_BYTE;
123 newdata->d_size = content->len;
124 newdata->d_off = offset;
125 newdata->d_align = first ? asmsubscn->max_align : 1;
127 offset += content->len;
129 while ((content = content->next) != asmsubscn->content);
131 while ((asmsubscn = asmsubscn->subnext) != NULL);
135 /* Create the symbol table if necessary. */
136 if (ctx->nsymbol_tab > 0)
138 /* Create the symbol table and string table section names. */
139 symscn_strent = ebl_strtabadd (ctx->section_strtab, ".symtab", 8);
140 strscn_strent = ebl_strtabadd (ctx->section_strtab, ".strtab", 8);
142 /* Create the symbol string table section. */
143 Elf_Scn *strscn = elf_newscn (ctx->out.elf);
144 strtabdata = elf_newdata (strscn);
145 shdr = gelf_getshdr (strscn, &shdr_mem);
146 if (strtabdata == NULL || shdr == NULL)
148 __libasm_seterrno (ASM_E_LIBELF);
151 strscnndx = elf_ndxscn (strscn);
153 ebl_strtabfinalize (ctx->symbol_strtab, strtabdata);
155 shdr->sh_type = SHT_STRTAB;
156 assert (shdr->sh_entsize == 0);
158 (void) gelf_update_shdr (strscn, shdr);
160 /* Create the symbol table section. */
161 Elf_Scn *symscn = elf_newscn (ctx->out.elf);
162 data = elf_newdata (symscn);
163 shdr = gelf_getshdr (symscn, &shdr_mem);
164 if (data == NULL || shdr == NULL)
166 __libasm_seterrno (ASM_E_LIBELF);
169 symscnndx = elf_ndxscn (symscn);
171 /* We know how many symbols there will be in the symbol table. */
172 data->d_size = gelf_fsize (ctx->out.elf, ELF_T_SYM,
173 ctx->nsymbol_tab + 1, EV_CURRENT);
174 symtab = malloc (data->d_size);
177 data->d_buf = symtab;
178 data->d_type = ELF_T_SYM;
181 /* Clear the first entry. */
183 memset (&syment, '\0', sizeof (syment));
184 (void) gelf_update_sym (data, 0, &syment);
186 /* Iterate over the symbol table. */
188 int ptr_local = 1; /* Start with index 1; zero remains unused. */
189 int ptr_nonlocal = ctx->nsymbol_tab;
190 uint32_t *xshndx = NULL;
192 while ((sym = asm_symbol_tab_iterate (&ctx->symbol_tab, &runp)) != NULL)
193 if (asm_emit_symbol_p (ebl_string (sym->strent)))
195 assert (ptr_local <= ptr_nonlocal);
197 syment.st_name = ebl_strtaboffset (sym->strent);
198 syment.st_info = GELF_ST_INFO (sym->binding, sym->type);
200 syment.st_value = sym->scn->offset + sym->offset;
201 syment.st_size = sym->size;
203 /* Add local symbols at the beginning, the other from
205 int ptr = sym->binding == STB_LOCAL ? ptr_local++ : ptr_nonlocal--;
207 /* Determine the section index. We have to handle the
208 overflow correctly. */
209 Elf_Scn *scn = (sym->scn->subsection_id == 0
210 ? sym->scn->data.main.scn
211 : sym->scn->data.up->data.main.scn);
214 if (unlikely (scn == ASM_ABS_SCN))
216 else if (unlikely (scn == ASM_COM_SCN))
218 else if (unlikely ((ndx = elf_ndxscn (scn)) >= SHN_LORESERVE))
220 if (unlikely (xshndx == NULL))
222 /* The extended section index section does not yet
226 xndxscn = elf_newscn (ctx->out.elf);
227 xndxdata = elf_newdata (xndxscn);
228 shdr = gelf_getshdr (xndxscn, &shdr_mem);
229 if (xndxdata == NULL || shdr == NULL)
231 __libasm_seterrno (ASM_E_LIBELF);
234 xndxscnndx = elf_ndxscn (xndxscn);
236 shdr->sh_type = SHT_SYMTAB_SHNDX;
237 shdr->sh_entsize = sizeof (Elf32_Word);
238 shdr->sh_addralign = sizeof (Elf32_Word);
239 shdr->sh_link = symscnndx;
241 (void) gelf_update_shdr (xndxscn, shdr);
243 xndxscn_strent = ebl_strtabadd (ctx->section_strtab,
244 ".symtab_shndx", 14);
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 = ebl_strtabadd (ctx->section_strtab, ".shstrtab", 10);
304 ebl_strtabfinalize (ctx->section_strtab, shstrtabdata);
306 shdr->sh_type = SHT_STRTAB;
307 assert (shdr->sh_entsize == 0);
308 shdr->sh_name = ebl_strtaboffset (shstrscn_strent);
310 (void) gelf_update_shdr (shstrscn, shdr);
313 /* Create the section groups. */
314 if (ctx->groups != NULL)
316 AsmScnGrp_t *runp = ctx->groups->next;
324 assert (scn != NULL);
325 shdr = gelf_getshdr (scn, &shdr_mem);
326 assert (shdr != NULL);
328 data = elf_newdata (scn);
331 __libasm_seterrno (ASM_E_LIBELF);
335 /* It is correct to use 'elf32_fsize' instead of 'gelf_fsize'
337 data->d_size = elf32_fsize (ELF_T_WORD, runp->nmembers + 1,
339 grpdata = data->d_buf = malloc (data->d_size);
342 data->d_type = ELF_T_WORD;
344 data->d_align = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
346 /* The first word of the section is filled with the flag word. */
347 *grpdata++ = runp->flags;
349 if (runp->members != NULL)
351 AsmScn_t *member = runp->members->data.main.next_in_group;
355 /* Only sections, not subsections, can be registered
356 as member of a group. The subsections get
357 automatically included. */
358 assert (member->subsection_id == 0);
360 *grpdata++ = elf_ndxscn (member->data.main.scn);
362 while ((member = member->data.main.next_in_group)
363 != runp->members->data.main.next_in_group);
366 /* Construct the section header. */
367 shdr->sh_name = ebl_strtaboffset (runp->strent);
368 shdr->sh_type = SHT_GROUP;
370 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 shdr->sh_info = (runp->signature != NULL
374 ? runp->signature->symidx : 0);
376 (void) gelf_update_shdr (scn, shdr);
378 while ((runp = runp->next) != ctx->groups->next);
382 /* Add the name to the symbol section. */
383 if (likely (symscnndx != 0))
385 Elf_Scn *scn = elf_getscn (ctx->out.elf, symscnndx);
387 shdr = gelf_getshdr (scn, &shdr_mem);
389 shdr->sh_name = ebl_strtaboffset (symscn_strent);
391 (void) gelf_update_shdr (scn, shdr);
394 /* Add the name to the string section. */
395 assert (strscnndx != 0);
396 scn = elf_getscn (ctx->out.elf, strscnndx);
398 shdr = gelf_getshdr (scn, &shdr_mem);
400 shdr->sh_name = ebl_strtaboffset (strscn_strent);
402 (void) gelf_update_shdr (scn, shdr);
405 /* Add the name to the extended symbol index section. */
408 scn = elf_getscn (ctx->out.elf, xndxscnndx);
410 shdr = gelf_getshdr (scn, &shdr_mem);
412 shdr->sh_name = ebl_strtaboffset (xndxscn_strent);
414 (void) gelf_update_shdr (scn, shdr);
419 /* Iterate over the created sections and fill in the names. */
420 for (asmscn = ctx->section_list; asmscn != NULL; asmscn = asmscn->allnext)
422 shdr = gelf_getshdr (asmscn->data.main.scn, &shdr_mem);
423 /* This better should not fail. */
424 assert (shdr != NULL);
426 shdr->sh_name = ebl_strtaboffset (asmscn->data.main.strent);
428 /* We now know the maximum alignment. */
429 shdr->sh_addralign = asmscn->max_align;
431 (void) gelf_update_shdr (asmscn->data.main.scn, shdr);
434 /* Put the reference to the section header string table in the ELF
436 ehdr = gelf_getehdr (ctx->out.elf, &ehdr_mem);
437 assert (ehdr != NULL);
439 shstrscnndx = elf_ndxscn (shstrscn);
440 if (unlikely (shstrscnndx > SHN_HIRESERVE)
441 || unlikely (shstrscnndx == SHN_XINDEX))
443 /* The index of the section header string sectio is too large. */
444 Elf_Scn *scn = elf_getscn (ctx->out.elf, 0);
446 /* Get the header for the zeroth section. */
447 shdr = gelf_getshdr (scn, &shdr_mem);
448 /* This better does not fail. */
449 assert (shdr != NULL);
451 /* The sh_link field of the zeroth section header contains the value. */
452 shdr->sh_link = shstrscnndx;
454 (void) gelf_update_shdr (scn, shdr);
456 /* This is the sign for the overflow. */
457 ehdr->e_shstrndx = SHN_XINDEX;
460 ehdr->e_shstrndx = elf_ndxscn (shstrscn);
462 gelf_update_ehdr (ctx->out.elf, ehdr);
464 /* Write out the ELF file. */
465 if (unlikely (elf_update (ctx->out.elf, ELF_C_WRITE_MMAP)) < 0)
467 __libasm_seterrno (ASM_E_LIBELF);
471 /* We do not need the section header and symbol string tables anymore. */
472 free (shstrtabdata->d_buf);
473 if (strtabdata != NULL)
474 free (strtabdata->d_buf);
475 /* We might have allocated the extended symbol table index. */
476 if (xndxdata != NULL)
477 free (xndxdata->d_buf);
479 /* Free section groups memory. */
480 AsmScnGrp_t *scngrp = ctx->groups;
483 free (elf_getdata (scngrp->scn, NULL)->d_buf);
484 while ((scngrp = scngrp->next) != ctx->groups);
486 /* Finalize the ELF handling. */
487 if (unlikely (elf_end (ctx->out.elf)) != 0)
489 __libasm_seterrno (ASM_E_LIBELF);
493 /* Free the temporary resources. */
501 asm_end (AsmCtx_t *ctx)
506 /* Something went wrong earlier. */
509 result = unlikely (ctx->textp) ? text_end (ctx) : binary_end (ctx);
513 /* Make the new file globally readable and user/group-writable. */
514 if (fchmod (ctx->fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) != 0)
516 __libasm_seterrno (ASM_E_CANNOT_CHMOD);
520 /* Rename output file. */
521 if (rename (ctx->tmp_fname, ctx->fname) != 0)
523 __libasm_seterrno (ASM_E_CANNOT_RENAME);
527 /* Free the resources. */
528 __libasm_finictx (ctx);
535 free_section (AsmScn_t *scnp)
539 if (scnp->subnext != NULL)
540 free_section (scnp->subnext);
542 struct AsmData *data = scnp->content;
550 while (oldp != scnp->content);
558 __libasm_finictx (AsmCtx_t *ctx)
560 /* Iterate through section table and free individual entries. */
561 AsmScn_t *scn = ctx->section_list;
564 AsmScn_t *oldp = scn;
569 /* Free the resources of the symbol table. */
572 while ((sym = asm_symbol_tab_iterate (&ctx->symbol_tab, &runp)) != NULL)
574 asm_symbol_tab_free (&ctx->symbol_tab);
577 /* Free section groups. */
578 AsmScnGrp_t *scngrp = ctx->groups;
582 AsmScnGrp_t *oldp = scngrp;
584 scngrp = scngrp->next;
587 while (scngrp != ctx->groups);
590 if (unlikely (ctx->textp))
592 /* Close the stream. */
593 fclose (ctx->out.file);
597 /* Close the output file. */
598 /* XXX We should test for errors here but what would we do if we'd
600 (void) close (ctx->fd);
602 /* And the string tables. */
603 ebl_strtabfree (ctx->section_strtab);
604 ebl_strtabfree (ctx->symbol_strtab);
607 /* Initialize the lock. */
608 rwlock_fini (ctx->lock);
610 /* Finally free the data structure. */