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