• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Create descriptor for assembling.
2    Copyright (C) 2002, 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 <errno.h>
36 #include <stdio.h>
37 #include <stdio_ext.h>
38 #include <stdlib.h>
39 #include <string.h>
40 
41 #include <gelf.h>
42 #include "libasmP.h"
43 
44 
45 static AsmCtx_t *
prepare_text_output(AsmCtx_t * result)46 prepare_text_output (AsmCtx_t *result)
47 {
48   if (result->fd == -1)
49     result->out.file = stdout;
50   else
51     {
52       result->out.file = fdopen (result->fd, "a");
53       if (result->out.file == NULL)
54 	{
55 	  close (result->fd);
56 	  free (result);
57 	  result = NULL;
58 	}
59       else
60 	__fsetlocking (result->out.file, FSETLOCKING_BYCALLER);
61     }
62 
63   return result;
64 }
65 
66 
67 static AsmCtx_t *
prepare_binary_output(AsmCtx_t * result,Ebl * ebl)68 prepare_binary_output (AsmCtx_t *result, Ebl *ebl)
69 {
70   GElf_Ehdr *ehdr;
71   GElf_Ehdr ehdr_mem;
72 
73   /* Create the ELF descriptor for the file.  */
74   result->out.elf = elf_begin (result->fd, ELF_C_WRITE_MMAP, NULL);
75   if (result->out.elf == NULL)
76     {
77     err_libelf:
78       unlink (result->tmp_fname);
79       close (result->fd);
80       free (result);
81       __libasm_seterrno (ASM_E_LIBELF);
82       return NULL;
83     }
84 
85   /* Create the ELF header for the output file.  */
86   int class = ebl_get_elfclass (ebl);
87   if (gelf_newehdr (result->out.elf, class) == 0)
88     goto err_libelf;
89 
90   ehdr = gelf_getehdr (result->out.elf, &ehdr_mem);
91   /* If this failed we are in trouble.  */
92   assert (ehdr != NULL);
93 
94   /* We create an object file.  */
95   ehdr->e_type = ET_REL;
96   /* Set the ELF version.  */
97   ehdr->e_version = EV_CURRENT;
98 
99   /* Use the machine, class, and endianness values from the Ebl descriptor.  */
100   ehdr->e_machine = ebl_get_elfmachine (ebl);
101   ehdr->e_ident[EI_CLASS] = class;
102   ehdr->e_ident[EI_DATA] = ebl_get_elfdata (ebl);
103 
104   memcpy (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG);
105 
106   /* Write the ELF header information back.  */
107   (void) gelf_update_ehdr (result->out.elf, ehdr);
108 
109   /* No section so far.  */
110   result->section_list = NULL;
111 
112   /* Initialize the hash table.  */
113   asm_symbol_tab_init (&result->symbol_tab, 67);
114   result->nsymbol_tab = 0;
115   /* And the string tables.  */
116   result->section_strtab = dwelf_strtab_init (true);
117   result->symbol_strtab = dwelf_strtab_init (true);
118 
119   /* We have no section groups so far.  */
120   result->groups = NULL;
121   result->ngroups = 0;
122 
123   return result;
124 }
125 
126 
127 AsmCtx_t *
asm_begin(const char * fname,Ebl * ebl,bool textp)128 asm_begin (const char *fname, Ebl *ebl, bool textp)
129 {
130   if (fname == NULL && ! textp)
131     return NULL;
132 
133   size_t fname_len = fname != NULL ? strlen (fname) : 0;
134 
135   /* Create the file descriptor.  We do not generate the output file
136      right away.  Instead we create a temporary file in the same
137      directory which, if everything goes alright, will replace a
138      possibly existing file with the given name.  */
139   AsmCtx_t *result = malloc (sizeof (AsmCtx_t) + 2 * fname_len + 9);
140   if (result == NULL)
141     return NULL;
142 
143       /* Initialize the lock.  */
144       rwlock_init (result->lock);
145 
146   if (fname != NULL)
147     {
148       /* Create the name of the temporary file.  */
149       result->fname = stpcpy (mempcpy (result->tmp_fname, fname, fname_len),
150 			      ".XXXXXX") + 1;
151       memcpy (result->fname, fname, fname_len + 1);
152 
153       /* Create the temporary file.  */
154       result->fd = mkstemp (result->tmp_fname);
155       if (result->fd == -1)
156 	{
157 	  int save_errno = errno;
158 	  free (result);
159 	  __libasm_seterrno (ASM_E_CANNOT_CREATE);
160 	  errno = save_errno;
161 	  return NULL;
162 	}
163     }
164   else
165     result->fd = -1;
166 
167   /* Initialize the counter for temporary symbols.  */
168   result->tempsym_count = 0;
169 
170   /* Now we differentiate between textual and binary output.   */
171   result->textp = textp;
172   if (textp)
173     result = prepare_text_output (result);
174   else
175     result = prepare_binary_output (result, ebl);
176 
177   return result;
178 }
179