Home | History | Annotate | Download | only in libelf
      1 /* Append new section.
      2    Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
      3    Written by Ulrich Drepper <drepper (at) redhat.com>, 1998.
      4 
      5    This program is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by
      7    the Free Software Foundation, version 2.
      8 
      9    This program is distributed in the hope that it will be useful,
     10    but WITHOUT ANY WARRANTY; without even the implied warranty of
     11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12    GNU General Public License for more details.
     13 
     14    You should have received a copy of the GNU General Public License
     15    along with this program; if not, write to the Free Software Foundation,
     16    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
     17 
     18 #ifdef HAVE_CONFIG_H
     19 # include <config.h>
     20 #endif
     21 
     22 #include <assert.h>
     23 #include <stdbool.h>
     24 #include <stddef.h>
     25 #include <stdlib.h>
     26 #include <string.h>
     27 
     28 #include "libelfP.h"
     29 
     30 
     31 Elf_Scn *
     32 elf_newscn (elf)
     33      Elf *elf;
     34 {
     35   Elf_Scn *result = NULL;
     36   bool first = false;
     37 
     38   if (elf == NULL)
     39     return NULL;
     40 
     41   /* We rely on the prefix of the `elf', `elf32', and `elf64' element
     42      being the same.  */
     43   assert (offsetof (Elf, state.elf.scns_last)
     44 	  == offsetof (Elf, state.elf32.scns_last));
     45   assert (offsetof (Elf, state.elf.scns_last)
     46 	  == offsetof (Elf, state.elf64.scns_last));
     47   assert (offsetof (Elf, state.elf32.scns)
     48 	  == offsetof (Elf, state.elf64.scns));
     49 
     50   rwlock_wrlock (elf->lock);
     51 
     52  again:
     53   if (elf->state.elf.scns_last->cnt < elf->state.elf.scns_last->max)
     54     {
     55       result = &elf->state.elf.scns_last->data[elf->state.elf.scns_last->cnt];
     56 
     57       if (++elf->state.elf.scns_last->cnt == 1
     58 	  && (elf->state.elf.scns_last
     59 	      == (elf->class == ELFCLASS32
     60 		  || (offsetof (Elf, state.elf32.scns)
     61 		      == offsetof (Elf, state.elf64.scns))
     62 		  ? &elf->state.elf32.scns : &elf->state.elf64.scns)))
     63 	/* This is zeroth section.  */
     64 	first = true;
     65       else
     66 	{
     67 	  assert (elf->state.elf.scns_last->cnt > 1);
     68 	  result->index = result[-1].index + 1;
     69 	}
     70     }
     71   else
     72     {
     73       /* We must allocate a new element.  */
     74       Elf_ScnList *newp;
     75 
     76       assert (elf->state.elf.scnincr > 0);
     77 
     78       newp = (Elf_ScnList *) calloc (sizeof (Elf_ScnList)
     79 				     + ((elf->state.elf.scnincr *= 2)
     80 					* sizeof (Elf_Scn)), 1);
     81       if (newp == NULL)
     82 	{
     83 	  __libelf_seterrno (ELF_E_NOMEM);
     84 	  goto out;
     85 	}
     86 
     87       result = &newp->data[0];
     88 
     89       /* One section used.  */
     90       ++newp->cnt;
     91 
     92       /* This is the number of sections we allocated.  */
     93       newp->max = elf->state.elf.scnincr;
     94 
     95       /* Remember the index for the first section in this block.  */
     96       newp->data[0].index
     97 	= 1 + elf->state.elf.scns_last->data[elf->state.elf.scns_last->max - 1].index;
     98 
     99       /* Enqueue the new list element.  */
    100       elf->state.elf.scns_last = elf->state.elf.scns_last->next = newp;
    101     }
    102 
    103   /* Create a section header for this section.  */
    104   if (elf->class == ELFCLASS32)
    105     {
    106       result->shdr.e32 = (Elf32_Shdr *) calloc (1, sizeof (Elf32_Shdr));
    107       if (result->shdr.e32 == NULL)
    108 	{
    109 	  __libelf_seterrno (ELF_E_NOMEM);
    110 	  goto out;
    111 	}
    112     }
    113   else
    114     {
    115       result->shdr.e64 = (Elf64_Shdr *) calloc (1, sizeof (Elf64_Shdr));
    116       if (result->shdr.e64 == NULL)
    117 	{
    118 	  __libelf_seterrno (ELF_E_NOMEM);
    119 	  goto out;
    120 	}
    121     }
    122 
    123   result->elf = elf;
    124   result->shdr_flags = ELF_F_DIRTY | ELF_F_MALLOCED;
    125   result->list = elf->state.elf.scns_last;
    126 
    127   /* Initialize the data part.  */
    128   result->data_read = 1;
    129   if (unlikely (first))
    130     {
    131       /* For the first section we mark the data as already available.  */
    132       //result->data_list_rear = &result->data_list;
    133       first = false;
    134       goto again;
    135     }
    136 
    137   result->flags |= ELF_F_DIRTY;
    138 
    139  out:
    140   rwlock_unlock (elf->lock);
    141 
    142   return result;
    143 }
    144