• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Create new section in output file.
2    Copyright (C) 2002 Red Hat, Inc.
3    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
4 
5    This program is Open Source software; you can redistribute it and/or
6    modify it under the terms of the Open Software License version 1.0 as
7    published by the Open Source Initiative.
8 
9    You should have received a copy of the Open Software License along
10    with this program; if not, you may obtain a copy of the Open Software
11    License version 1.0 from http://www.opensource.org/licenses/osl.php or
12    by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
13    3001 King Ranch Road, Ukiah, CA 95482.   */
14 
15 #ifdef HAVE_CONFIG_H
16 # include <config.h>
17 #endif
18 
19 #include <assert.h>
20 #include <error.h>
21 #include <libintl.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include <libasmP.h>
26 #include <libelf.h>
27 #include <system.h>
28 
29 
30 /* Memory for the default pattern.  The type uses a flexible array
31    which does work well with a static initializer.  So we play some
32    dirty tricks here.  */
33 static const struct
34 {
35   struct FillPattern pattern;
36   char zero;
37 } xdefault_pattern =
38   {
39     .pattern =
40     {
41       .len = 1
42     },
43     .zero = '\0'
44   };
45 const struct FillPattern *__libasm_default_pattern = &xdefault_pattern.pattern;
46 
47 
48 static AsmScn_t *
text_newscn(AsmScn_t * result,GElf_Word type,GElf_Xword flags)49 text_newscn (AsmScn_t *result, GElf_Word type, GElf_Xword flags)
50 {
51   /* Buffer where we construct the flag string.  */
52   char flagstr[sizeof (GElf_Xword) * 8 + 5];
53   char *wp = flagstr;
54   const char *typestr = "";
55 
56   /* Only write out the flag string if this is the first time the
57      section is selected.  Some assemblers cannot cope with the
58      .section pseudo-op otherwise.  */
59   wp = stpcpy (wp, ", \"");
60 
61   if (flags & SHF_WRITE)
62     *wp++ = 'w';
63   if (flags & SHF_ALLOC)
64     *wp++ = 'a';
65   if (flags & SHF_EXECINSTR)
66     *wp++ = 'x';
67   if (flags & SHF_MERGE)
68     *wp++ = 'M';
69   if (flags & SHF_STRINGS)
70     *wp++ = 'S';
71   if (flags & SHF_LINK_ORDER)
72     *wp++ = 'L';
73 
74   *wp++ = '"';
75 
76   if (type == SHT_PROGBITS)
77     typestr = ",@progbits";
78   else if (type == SHT_NOBITS)
79     typestr = ",@nobits";
80 
81   /* Terminate the string.  */
82   *wp = '\0';
83 
84   printf ("\t.section \"%s\"%s%s\n", result->name, flagstr, typestr);
85 
86   return result;
87 }
88 
89 
90 static AsmScn_t *
binary_newscn(AsmScn_t * result,GElf_Word type,GElf_Xword flags,size_t scnname_len)91 binary_newscn (AsmScn_t *result, GElf_Word type, GElf_Xword flags,
92 	       size_t scnname_len)
93 {
94   GElf_Shdr shdr_mem;
95   GElf_Shdr *shdr;
96   Elf_Scn *scn;
97 
98   /* The initial subsection has the number zero.  */
99   result->subsection_id = 0;
100 
101   /* We start at offset zero.  */
102   result->offset = 0;
103   /* And generic alignment.  */
104   result->max_align = 1;
105 
106   /* No output yet.  */
107   result->content = NULL;
108 
109   /* Put the default fill pattern in place.  */
110   result->pattern = (struct FillPattern *) __libasm_default_pattern;
111 
112   /* There are no subsections so far.  */
113   result->subnext = NULL;
114 
115   /* Add the name to the section header string table.  */
116   result->data.main.strent = ebl_strtabadd (result->ctx->section_strtab,
117 					    result->name, scnname_len);
118   assert (result->data.main.strent != NULL);
119 
120   /* Create the new ELF section.  */
121   result->data.main.scn = scn = elf_newscn (result->ctx->out.elf);
122   if (scn == NULL)
123     {
124       free (result);
125       __libasm_seterrno (ASM_E_LIBELF);
126       return NULL;
127     }
128 
129   /* Not part of a section group (yet).  */
130   result->data.main.next_in_group = NULL;
131 
132   /* Remember the flags.  */
133   shdr = gelf_getshdr (scn, &shdr_mem);
134 
135   shdr->sh_flags = flags;
136   result->type = shdr->sh_type = type;
137 
138   (void) gelf_update_shdr (scn, shdr);
139 
140   return result;
141 }
142 
143 
144 AsmScn_t *
asm_newscn(ctx,scnname,type,flags)145 asm_newscn (ctx, scnname, type, flags)
146      AsmCtx_t *ctx;
147      const char *scnname;
148      GElf_Word type;
149      GElf_Xword flags;
150 {
151   size_t scnname_len = strlen (scnname) + 1;
152   unsigned long int hval;
153   AsmScn_t *result;
154 
155   /* If no context is given there might be an earlier error.  */
156   if (ctx == NULL)
157     return NULL;
158 
159   /* Check whether only flags are set which areselectable by the user.  */
160   if (unlikely ((flags & ~(SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE
161 			   | SHF_STRINGS | SHF_LINK_ORDER)) != 0)
162       /* We allow only two section types: data and data without file
163 	 representation.  */
164       || (type != SHT_PROGBITS && unlikely (type != SHT_NOBITS)))
165     {
166       __libasm_seterrno (ASM_E_INVALID);
167       return NULL;
168     }
169 
170   hval = elf_hash (scnname);
171 
172   rwlock_wrlock (ctx->lock);
173 
174   /* This is a new section.  */
175   result = (AsmScn_t *) malloc (sizeof (AsmScn_t) + scnname_len);
176   if (result != NULL)
177     {
178       /* Add the name.  */
179       memcpy (result->name, scnname, scnname_len);
180 
181       /* Add the reference to the context.  */
182       result->ctx = ctx;
183 
184       /* Perform operations according to output mode.  */
185       result = (unlikely (ctx->textp)
186 		? text_newscn (result, type, flags)
187 		: binary_newscn (result, type, flags, scnname_len));
188 
189       /* If everything went well finally add the new section to the hash
190 	 table.  */
191       if (result != NULL)
192 	{
193 	  result->allnext = ctx->section_list;
194 	  ctx->section_list = result;
195 	}
196     }
197 
198   rwlock_unlock (ctx->lock);
199 
200   return result;
201 }
202 INTDEF(asm_newscn)
203