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