• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Create new section in output file.
2    Copyright (C) 2002-2011, 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 <libintl.h>
36 #include <stdlib.h>
37 #include <string.h>
38 
39 #include <libasmP.h>
40 #include <libelf.h>
41 #include <system.h>
42 
43 
44 /* Memory for the default pattern.  The type uses a flexible array
45    which does work well with a static initializer.  So we play some
46    dirty tricks here.  */
47 static const struct
48 {
49   struct FillPattern pattern;
50   char zero;
51 } xdefault_pattern =
52   {
53     .pattern =
54     {
55       .len = 1
56     },
57     .zero = '\0'
58   };
59 const struct FillPattern *__libasm_default_pattern = &xdefault_pattern.pattern;
60 
61 
62 static AsmScn_t *
text_newscn(AsmScn_t * result,GElf_Word type,GElf_Xword flags)63 text_newscn (AsmScn_t *result, GElf_Word type, GElf_Xword flags)
64 {
65   /* Buffer where we construct the flag string.  */
66   char flagstr[sizeof (GElf_Xword) * 8 + 5];
67   char *wp = flagstr;
68   const char *typestr = "";
69 
70   /* Only write out the flag string if this is the first time the
71      section is selected.  Some assemblers cannot cope with the
72      .section pseudo-op otherwise.  */
73   wp = stpcpy (wp, ", \"");
74 
75   if (flags & SHF_WRITE)
76     *wp++ = 'w';
77   if (flags & SHF_ALLOC)
78     *wp++ = 'a';
79   if (flags & SHF_EXECINSTR)
80     *wp++ = 'x';
81   if (flags & SHF_MERGE)
82     *wp++ = 'M';
83   if (flags & SHF_STRINGS)
84     *wp++ = 'S';
85   if (flags & SHF_LINK_ORDER)
86     *wp++ = 'L';
87 
88   *wp++ = '"';
89 
90   if (type == SHT_PROGBITS)
91     typestr = ",@progbits";
92   else if (type == SHT_NOBITS)
93     typestr = ",@nobits";
94 
95   /* Terminate the string.  */
96   *wp = '\0';
97 
98   fprintf (result->ctx->out.file, "\t.section \"%s\"%s%s\n",
99 	   result->name, flagstr, typestr);
100 
101   return result;
102 }
103 
104 
105 static AsmScn_t *
binary_newscn(AsmScn_t * result,GElf_Word type,GElf_Xword flags,size_t scnname_len)106 binary_newscn (AsmScn_t *result, GElf_Word type, GElf_Xword flags,
107 	       size_t scnname_len)
108 {
109   GElf_Shdr shdr_mem;
110   GElf_Shdr *shdr;
111   Elf_Scn *scn;
112 
113   /* The initial subsection has the number zero.  */
114   result->subsection_id = 0;
115 
116   /* We start at offset zero.  */
117   result->offset = 0;
118   /* And generic alignment.  */
119   result->max_align = 1;
120 
121   /* No output yet.  */
122   result->content = NULL;
123 
124   /* Put the default fill pattern in place.  */
125   result->pattern = (struct FillPattern *) __libasm_default_pattern;
126 
127   /* There are no subsections so far.  */
128   result->subnext = NULL;
129 
130   /* Add the name to the section header string table.  */
131   result->data.main.strent = dwelf_strtab_add_len (result->ctx->section_strtab,
132 						   result->name, scnname_len);
133   assert (result->data.main.strent != NULL);
134 
135   /* Create the new ELF section.  */
136   result->data.main.scn = scn = elf_newscn (result->ctx->out.elf);
137   if (scn == NULL)
138     {
139       free (result);
140       __libasm_seterrno (ASM_E_LIBELF);
141       return NULL;
142     }
143 
144   /* Not part of a section group (yet).  */
145   result->data.main.next_in_group = NULL;
146 
147   /* Remember the flags.  */
148   shdr = gelf_getshdr (scn, &shdr_mem);
149 
150   shdr->sh_flags = flags;
151   result->type = shdr->sh_type = type;
152 
153   (void) gelf_update_shdr (scn, shdr);
154 
155   return result;
156 }
157 
158 
159 AsmScn_t *
asm_newscn(AsmCtx_t * ctx,const char * scnname,GElf_Word type,GElf_Xword flags)160 asm_newscn (AsmCtx_t *ctx, const char *scnname, GElf_Word type,
161 	    GElf_Xword flags)
162 {
163   size_t scnname_len = strlen (scnname) + 1;
164   AsmScn_t *result;
165 
166   /* If no context is given there might be an earlier error.  */
167   if (ctx == NULL)
168     return NULL;
169 
170   /* Check whether only flags are set which areselectable by the user.  */
171   if (unlikely ((flags & ~(SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE
172 			   | SHF_STRINGS | SHF_LINK_ORDER)) != 0)
173       /* We allow only two section types: data and data without file
174 	 representation.  */
175       || (type != SHT_PROGBITS && unlikely (type != SHT_NOBITS)))
176     {
177       __libasm_seterrno (ASM_E_INVALID);
178       return NULL;
179     }
180 
181   rwlock_wrlock (ctx->lock);
182 
183   /* This is a new section.  */
184   result = (AsmScn_t *) malloc (sizeof (AsmScn_t) + scnname_len);
185   if (result != NULL)
186     {
187       /* Add the name.  */
188       memcpy (result->name, scnname, scnname_len);
189 
190       /* Add the reference to the context.  */
191       result->ctx = ctx;
192 
193       /* Perform operations according to output mode.  */
194       result = (unlikely (ctx->textp)
195 		? text_newscn (result, type, flags)
196 		: binary_newscn (result, type, flags, scnname_len));
197 
198       /* If everything went well finally add the new section to the hash
199 	 table.  */
200       if (result != NULL)
201 	{
202 	  result->allnext = ctx->section_list;
203 	  ctx->section_list = result;
204 	}
205     }
206 
207   rwlock_unlock (ctx->lock);
208 
209   return result;
210 }
211 INTDEF(asm_newscn)
212