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. */ 46static 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 }; 58const struct FillPattern *__libasm_default_pattern = &xdefault_pattern.pattern; 59 60 61static AsmScn_t * 62text_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 104static AsmScn_t * 105binary_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 158AsmScn_t * 159asm_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} 210INTDEF(asm_newscn) 211