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