Home | History | Annotate | Download | only in libelf
      1 /* Append new section.
      2    Copyright (C) 1998,1999,2000,2001,2002,2005,2009,2014,2015 Red Hat, Inc.
      3    This file is part of elfutils.
      4    Written by Ulrich Drepper <drepper (at) redhat.com>, 1998.
      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 <stdbool.h>
     36 #include <stddef.h>
     37 #include <stdlib.h>
     38 #include <string.h>
     39 
     40 #include "libelfP.h"
     41 
     42 
     43 Elf_Scn *
     44 elf_newscn (Elf *elf)
     45 {
     46   Elf_Scn *result = NULL;
     47   bool first = false;
     48 
     49   if (elf == NULL)
     50     return NULL;
     51 
     52   /* We rely on the prefix of the `elf', `elf32', and `elf64' element
     53      being the same.  */
     54   assert (offsetof (Elf, state.elf.scns_last)
     55 	  == offsetof (Elf, state.elf32.scns_last));
     56   assert (offsetof (Elf, state.elf.scns_last)
     57 	  == offsetof (Elf, state.elf64.scns_last));
     58   assert (offsetof (Elf, state.elf32.scns)
     59 	  == offsetof (Elf, state.elf64.scns));
     60 
     61   rwlock_wrlock (elf->lock);
     62 
     63  again:
     64   if (elf->state.elf.scns_last->cnt < elf->state.elf.scns_last->max)
     65     {
     66       result = &elf->state.elf.scns_last->data[elf->state.elf.scns_last->cnt];
     67 
     68       if (++elf->state.elf.scns_last->cnt == 1
     69 	  && (elf->state.elf.scns_last
     70 	      == (elf->class == ELFCLASS32
     71 		  || (offsetof (Elf, state.elf32.scns)
     72 		      == offsetof (Elf, state.elf64.scns))
     73 		  ? &elf->state.elf32.scns : &elf->state.elf64.scns)))
     74 	/* This is zeroth section.  */
     75 	first = true;
     76       else
     77 	{
     78 	  assert (elf->state.elf.scns_last->cnt > 1);
     79 	  result->index = result[-1].index + 1;
     80 	}
     81     }
     82   else
     83     {
     84       /* We must allocate a new element.  */
     85       Elf_ScnList *newp = NULL;
     86 
     87       assert (elf->state.elf.scnincr > 0);
     88 
     89       if (
     90 #if SIZE_MAX <= 4294967295U
     91 	  likely (elf->state.elf.scnincr
     92 		  < SIZE_MAX / 2 / sizeof (Elf_Scn) - sizeof (Elf_ScnList))
     93 #else
     94 	  1
     95 #endif
     96 	  )
     97       newp = (Elf_ScnList *) calloc (sizeof (Elf_ScnList)
     98 				     + ((elf->state.elf.scnincr *= 2)
     99 					* sizeof (Elf_Scn)), 1);
    100       if (newp == NULL)
    101 	{
    102 	  __libelf_seterrno (ELF_E_NOMEM);
    103 	  goto out;
    104 	}
    105 
    106       result = &newp->data[0];
    107 
    108       /* One section used.  */
    109       ++newp->cnt;
    110 
    111       /* This is the number of sections we allocated.  */
    112       newp->max = elf->state.elf.scnincr;
    113 
    114       /* Remember the index for the first section in this block.  */
    115       newp->data[0].index
    116 	= 1 + elf->state.elf.scns_last->data[elf->state.elf.scns_last->max - 1].index;
    117 
    118       /* Enqueue the new list element.  */
    119       elf->state.elf.scns_last = elf->state.elf.scns_last->next = newp;
    120     }
    121 
    122   /* Create a section header for this section.  */
    123   if (elf->class == ELFCLASS32)
    124     {
    125       result->shdr.e32 = (Elf32_Shdr *) calloc (1, sizeof (Elf32_Shdr));
    126       if (result->shdr.e32 == NULL)
    127 	{
    128 	  __libelf_seterrno (ELF_E_NOMEM);
    129 	  goto out;
    130 	}
    131     }
    132   else
    133     {
    134       result->shdr.e64 = (Elf64_Shdr *) calloc (1, sizeof (Elf64_Shdr));
    135       if (result->shdr.e64 == NULL)
    136 	{
    137 	  __libelf_seterrno (ELF_E_NOMEM);
    138 	  goto out;
    139 	}
    140     }
    141 
    142   result->elf = elf;
    143   result->shdr_flags = ELF_F_DIRTY | ELF_F_MALLOCED;
    144   result->list = elf->state.elf.scns_last;
    145 
    146   /* Initialize the data part.  */
    147   result->data_read = 1;
    148   if (unlikely (first))
    149     {
    150       /* For the first section we mark the data as already available.  */
    151       //result->data_list_rear = &result->data_list;
    152       first = false;
    153       goto again;
    154     }
    155 
    156   result->flags |= ELF_F_DIRTY;
    157 
    158  out:
    159   rwlock_unlock (elf->lock);
    160 
    161   return result;
    162 }
    163