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 Red Hat elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2002.
6 Red Hat elfutils is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by the
8 Free Software Foundation; version 2 of the License.
10 Red Hat elfutils is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with Red Hat elfutils; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
19 Red Hat elfutils is an included package of the Open Invention Network.
20 An included package of the Open Invention Network is a package for which
21 Open Invention Network licensees cross-license their patents. No patent
22 license is granted, either expressly or impliedly, by designation as an
23 included package. Should you wish to participate in the Open Invention
24 Network licensing program, please visit www.openinventionnetwork.com
25 <http://www.openinventionnetwork.com>. */
46 text_end (AsmCtx_t *ctx __attribute__ ((unused)))
48 if (fclose (ctx->out.file) != 0)
50 __libasm_seterrno (ASM_E_IOERROR);
59 binary_end (AsmCtx_t *ctx)
62 struct Ebl_Strent *symscn_strent = NULL;
63 struct Ebl_Strent *strscn_strent = NULL;
64 struct Ebl_Strent *xndxscn_strent = NULL;
66 struct Ebl_Strent *shstrscn_strent;
70 size_t xndxscnndx = 0;
72 Elf_Data *shstrtabdata;
73 Elf_Data *strtabdata = NULL;
74 Elf_Data *xndxdata = NULL;
82 /* Iterate over the created sections and compute the offsets of the
83 various subsections and fill in the content. */
84 for (asmscn = ctx->section_list; asmscn != NULL; asmscn = asmscn->allnext)
87 Elf_Scn *scn = elf_getscn (ctx->out.elf, asmscn->data.main.scnndx);
89 Elf_Scn *scn = asmscn->data.main.scn;
92 AsmScn_t *asmsubscn = asmscn;
96 struct AsmData *content = asmsubscn->content;
99 offset = ((offset + asmsubscn->max_align - 1)
100 & ~(asmsubscn->max_align - 1));
102 /* Update the offset for this subsection. This field now
103 stores the offset of the first by in this subsection. */
104 asmsubscn->offset = offset;
106 /* Note that the content list is circular. */
110 Elf_Data *newdata = elf_newdata (scn);
114 __libasm_seterrno (ASM_E_LIBELF);
118 newdata->d_buf = content->data;
119 newdata->d_type = ELF_T_BYTE;
120 newdata->d_size = content->len;
121 newdata->d_off = offset;
122 newdata->d_align = first ? asmsubscn->max_align : 1;
124 offset += content->len;
126 while ((content = content->next) != asmsubscn->content);
128 while ((asmsubscn = asmsubscn->subnext) != NULL);
132 /* Create the symbol table if necessary. */
133 if (ctx->nsymbol_tab > 0)
135 /* Create the symbol table and string table section names. */
136 symscn_strent = ebl_strtabadd (ctx->section_strtab, ".symtab", 8);
137 strscn_strent = ebl_strtabadd (ctx->section_strtab, ".strtab", 8);
139 /* Create the symbol string table section. */
140 Elf_Scn *strscn = elf_newscn (ctx->out.elf);
141 strtabdata = elf_newdata (strscn);
142 shdr = gelf_getshdr (strscn, &shdr_mem);
143 if (strtabdata == NULL || shdr == NULL)
145 __libasm_seterrno (ASM_E_LIBELF);
148 strscnndx = elf_ndxscn (strscn);
150 ebl_strtabfinalize (ctx->symbol_strtab, strtabdata);
152 shdr->sh_type = SHT_STRTAB;
153 assert (shdr->sh_entsize == 0);
155 (void) gelf_update_shdr (strscn, shdr);
157 /* Create the symbol table section. */
158 Elf_Scn *symscn = elf_newscn (ctx->out.elf);
159 data = elf_newdata (symscn);
160 shdr = gelf_getshdr (symscn, &shdr_mem);
161 if (data == NULL || shdr == NULL)
163 __libasm_seterrno (ASM_E_LIBELF);
166 symscnndx = elf_ndxscn (symscn);
168 /* We know how many symbols there will be in the symbol table. */
169 data->d_size = gelf_fsize (ctx->out.elf, ELF_T_SYM,
170 ctx->nsymbol_tab + 1, EV_CURRENT);
171 symtab = malloc (data->d_size);
174 data->d_buf = symtab;
175 data->d_type = ELF_T_SYM;
178 /* Clear the first entry. */
180 memset (&syment, '\0', sizeof (syment));
181 (void) gelf_update_sym (data, 0, &syment);
183 /* Iterate over the symbol table. */
185 int ptr_local = 1; /* Start with index 1; zero remains unused. */
186 int ptr_nonlocal = ctx->nsymbol_tab;
187 uint32_t *xshndx = NULL;
189 while ((sym = asm_symbol_tab_iterate (&ctx->symbol_tab, &runp)) != NULL)
190 if (asm_emit_symbol_p (ebl_string (sym->strent)))
192 assert (ptr_local <= ptr_nonlocal);
194 syment.st_name = ebl_strtaboffset (sym->strent);
195 syment.st_info = GELF_ST_INFO (sym->binding, sym->type);
197 syment.st_value = sym->scn->offset + sym->offset;
198 syment.st_size = sym->size;
200 /* Add local symbols at the beginning, the other from
202 int ptr = sym->binding == STB_LOCAL ? ptr_local++ : ptr_nonlocal--;
204 /* Determine the section index. We have to handle the
205 overflow correctly. */
206 Elf_Scn *scn = (sym->scn->subsection_id == 0
207 ? sym->scn->data.main.scn
208 : sym->scn->data.up->data.main.scn);
211 if (unlikely (scn == ASM_ABS_SCN))
213 else if (unlikely (scn == ASM_COM_SCN))
215 else if (unlikely ((ndx = elf_ndxscn (scn)) >= SHN_LORESERVE))
217 if (unlikely (xshndx == NULL))
219 /* The extended section index section does not yet
223 xndxscn = elf_newscn (ctx->out.elf);
224 xndxdata = elf_newdata (xndxscn);
225 shdr = gelf_getshdr (xndxscn, &shdr_mem);
226 if (xndxdata == NULL || shdr == NULL)
228 __libasm_seterrno (ASM_E_LIBELF);
231 xndxscnndx = elf_ndxscn (xndxscn);
233 shdr->sh_type = SHT_SYMTAB_SHNDX;
234 shdr->sh_entsize = sizeof (Elf32_Word);
235 shdr->sh_addralign = sizeof (Elf32_Word);
236 shdr->sh_link = symscnndx;
238 (void) gelf_update_shdr (xndxscn, shdr);
240 xndxscn_strent = ebl_strtabadd (ctx->section_strtab,
241 ".symtab_shndx", 14);
243 /* Note that using 'elf32_fsize' instead of
244 'gelf_fsize' here is correct. */
245 xndxdata->d_size = elf32_fsize (ELF_T_WORD,
246 ctx->nsymbol_tab + 1,
248 xshndx = xndxdata->d_buf = calloc (1, xndxdata->d_size);
251 /* Using ELF_T_WORD here relies on the fact that the
252 32- and 64-bit types are the same size. */
253 xndxdata->d_type = ELF_T_WORD;
257 /* Store the real section index in the extended setion
259 assert ((size_t) ptr < ctx->nsymbol_tab + 1);
262 /* And signal that this happened. */
265 syment.st_shndx = ndx;
267 /* Remember where we put the symbol. */
270 (void) gelf_update_sym (data, ptr, &syment);
273 assert (ptr_local == ptr_nonlocal + 1);
275 shdr->sh_type = SHT_SYMTAB;
276 shdr->sh_link = strscnndx;
277 shdr->sh_info = ptr_local;
278 shdr->sh_entsize = gelf_fsize (ctx->out.elf, ELF_T_SYM, 1, EV_CURRENT);
279 shdr->sh_addralign = gelf_fsize (ctx->out.elf, ELF_T_ADDR, 1,
282 (void) gelf_update_shdr (symscn, shdr);
286 /* Create the section header string table section and fill in the
287 references in the section headers. */
288 shstrscn = elf_newscn (ctx->out.elf);
289 shstrtabdata = elf_newdata (shstrscn);
290 shdr = gelf_getshdr (shstrscn, &shdr_mem);
291 if (shstrscn == NULL || shstrtabdata == NULL || shdr == NULL)
293 __libasm_seterrno (ASM_E_LIBELF);
298 /* Add the name of the section header string table. */
299 shstrscn_strent = ebl_strtabadd (ctx->section_strtab, ".shstrtab", 10);
301 ebl_strtabfinalize (ctx->section_strtab, shstrtabdata);
303 shdr->sh_type = SHT_STRTAB;
304 assert (shdr->sh_entsize == 0);
305 shdr->sh_name = ebl_strtaboffset (shstrscn_strent);
307 (void) gelf_update_shdr (shstrscn, shdr);
310 /* Create the section groups. */
311 if (ctx->groups != NULL)
313 AsmScnGrp_t *runp = ctx->groups->next;
321 assert (scn != NULL);
322 shdr = gelf_getshdr (scn, &shdr_mem);
323 assert (shdr != NULL);
325 data = elf_newdata (scn);
328 __libasm_seterrno (ASM_E_LIBELF);
332 /* It is correct to use 'elf32_fsize' instead of 'gelf_fsize'
334 data->d_size = elf32_fsize (ELF_T_WORD, runp->nmembers + 1,
336 grpdata = data->d_buf = malloc (data->d_size);
339 data->d_type = ELF_T_WORD;
341 data->d_align = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
343 /* The first word of the section is filled with the flag word. */
344 *grpdata++ = runp->flags;
346 if (runp->members != NULL)
348 AsmScn_t *member = runp->members->data.main.next_in_group;
352 /* Only sections, not subsections, can be registered
353 as member of a group. The subsections get
354 automatically included. */
355 assert (member->subsection_id == 0);
357 *grpdata++ = elf_ndxscn (member->data.main.scn);
359 while ((member = member->data.main.next_in_group)
360 != runp->members->data.main.next_in_group);
363 /* Construct the section header. */
364 shdr->sh_name = ebl_strtaboffset (runp->strent);
365 shdr->sh_type = SHT_GROUP;
367 shdr->sh_link = symscnndx;
368 /* If the user did not specify a signature we use the initial
369 empty symbol in the symbol table as the signature. */
370 shdr->sh_info = (runp->signature != NULL
371 ? runp->signature->symidx : 0);
373 (void) gelf_update_shdr (scn, shdr);
375 while ((runp = runp->next) != ctx->groups->next);
379 /* Add the name to the symbol section. */
380 if (likely (symscnndx != 0))
382 Elf_Scn *scn = elf_getscn (ctx->out.elf, symscnndx);
384 shdr = gelf_getshdr (scn, &shdr_mem);
386 shdr->sh_name = ebl_strtaboffset (symscn_strent);
388 (void) gelf_update_shdr (scn, shdr);
391 /* Add the name to the string section. */
392 assert (strscnndx != 0);
393 scn = elf_getscn (ctx->out.elf, strscnndx);
395 shdr = gelf_getshdr (scn, &shdr_mem);
397 shdr->sh_name = ebl_strtaboffset (strscn_strent);
399 (void) gelf_update_shdr (scn, shdr);
402 /* Add the name to the extended symbol index section. */
405 scn = elf_getscn (ctx->out.elf, xndxscnndx);
407 shdr = gelf_getshdr (scn, &shdr_mem);
409 shdr->sh_name = ebl_strtaboffset (xndxscn_strent);
411 (void) gelf_update_shdr (scn, shdr);
416 /* Iterate over the created sections and fill in the names. */
417 for (asmscn = ctx->section_list; asmscn != NULL; asmscn = asmscn->allnext)
419 shdr = gelf_getshdr (asmscn->data.main.scn, &shdr_mem);
420 /* This better should not fail. */
421 assert (shdr != NULL);
423 shdr->sh_name = ebl_strtaboffset (asmscn->data.main.strent);
425 /* We now know the maximum alignment. */
426 shdr->sh_addralign = asmscn->max_align;
428 (void) gelf_update_shdr (asmscn->data.main.scn, shdr);
431 /* Put the reference to the section header string table in the ELF
433 ehdr = gelf_getehdr (ctx->out.elf, &ehdr_mem);
434 assert (ehdr != NULL);
436 shstrscnndx = elf_ndxscn (shstrscn);
437 if (unlikely (shstrscnndx > SHN_HIRESERVE)
438 || unlikely (shstrscnndx == SHN_XINDEX))
440 /* The index of the section header string sectio is too large. */
441 Elf_Scn *scn = elf_getscn (ctx->out.elf, 0);
443 /* Get the header for the zeroth section. */
444 shdr = gelf_getshdr (scn, &shdr_mem);
445 /* This better does not fail. */
446 assert (shdr != NULL);
448 /* The sh_link field of the zeroth section header contains the value. */
449 shdr->sh_link = shstrscnndx;
451 (void) gelf_update_shdr (scn, shdr);
453 /* This is the sign for the overflow. */
454 ehdr->e_shstrndx = SHN_XINDEX;
457 ehdr->e_shstrndx = elf_ndxscn (shstrscn);
459 gelf_update_ehdr (ctx->out.elf, ehdr);
461 /* Write out the ELF file. */
462 if (unlikely (elf_update (ctx->out.elf, ELF_C_WRITE_MMAP)) < 0)
464 __libasm_seterrno (ASM_E_LIBELF);
468 /* We do not need the section header and symbol string tables anymore. */
469 free (shstrtabdata->d_buf);
470 if (strtabdata != NULL)
471 free (strtabdata->d_buf);
472 /* We might have allocated the extended symbol table index. */
473 if (xndxdata != NULL)
474 free (xndxdata->d_buf);
476 /* Free section groups memory. */
477 AsmScnGrp_t *scngrp = ctx->groups;
480 free (elf_getdata (scngrp->scn, NULL)->d_buf);
481 while ((scngrp = scngrp->next) != ctx->groups);
483 /* Finalize the ELF handling. */
484 if (unlikely (elf_end (ctx->out.elf)) != 0)
486 __libasm_seterrno (ASM_E_LIBELF);
490 /* Free the temporary resources. */
504 /* Something went wrong earlier. */
507 result = unlikely (ctx->textp) ? text_end (ctx) : binary_end (ctx);
511 /* Make the new file globally readable and user/group-writable. */
512 if (fchmod (ctx->fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) != 0)
514 __libasm_seterrno (ASM_E_CANNOT_CHMOD);
518 /* Rename output file. */
519 if (rename (ctx->tmp_fname, ctx->fname) != 0)
521 __libasm_seterrno (ASM_E_CANNOT_RENAME);
525 /* Free the resources. */
526 __libasm_finictx (ctx);
533 free_section (AsmScn_t *scnp)
537 if (scnp->subnext != NULL)
538 free_section (scnp->subnext);
540 struct AsmData *data = scnp->content;
548 while (oldp != scnp->content);
555 __libasm_finictx (ctx)
558 /* Iterate through section table and free individual entries. */
559 AsmScn_t *scn = ctx->section_list;
562 AsmScn_t *oldp = scn;
567 /* Free the resources of the symbol table. */
570 while ((sym = asm_symbol_tab_iterate (&ctx->symbol_tab, &runp)) != NULL)
572 asm_symbol_tab_free (&ctx->symbol_tab);
575 /* Free section groups. */
576 AsmScnGrp_t *scngrp = ctx->groups;
580 AsmScnGrp_t *oldp = scngrp;
582 scngrp = scngrp->next;
585 while (scngrp != ctx->groups);
588 if (unlikely (ctx->textp))
590 /* Close the stream. */
591 fclose (ctx->out.file);
595 /* Close the output file. */
596 /* XXX We should test for errors here but what would we do if we'd
598 (void) close (ctx->fd);
600 /* And the string tables. */
601 ebl_strtabfree (ctx->section_strtab);
602 ebl_strtabfree (ctx->symbol_strtab);
605 /* Initialize the lock. */
606 rwlock_fini (ctx->lock);
608 /* Finally free the data structure. */