tools/elf4rom/libs/libelf-0.8.10/lib/strptr.c
changeset 34 92d87f2e53c2
equal deleted inserted replaced
33:1af5c1be89f8 34:92d87f2e53c2
       
     1 /*
       
     2  * strptr.c - implementation of the elf_strptr(3) function.
       
     3  * Copyright (C) 1995 - 2007 Michael Riepe
       
     4  *
       
     5  * This library is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU Library General Public
       
     7  * License as published by the Free Software Foundation; either
       
     8  * version 2 of the License, or (at your option) any later version.
       
     9  *
       
    10  * This library is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13  * Library General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU Library General Public
       
    16  * License along with this library; if not, write to the Free Software
       
    17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    18  */
       
    19 
       
    20 #include <private.h>
       
    21 
       
    22 #ifndef lint
       
    23 static const char rcsid[] = "@(#) $Id: strptr.c,v 1.11 2007/09/07 12:07:59 michael Exp $";
       
    24 #endif /* lint */
       
    25 
       
    26 char*
       
    27 elf_strptr(Elf *elf, size_t section, size_t offset) {
       
    28     Elf_Data *data;
       
    29     Elf_Scn *scn;
       
    30     size_t n;
       
    31     char *s;
       
    32 
       
    33     if (!elf) {
       
    34 	return NULL;
       
    35     }
       
    36     elf_assert(elf->e_magic == ELF_MAGIC);
       
    37     if (!(scn = elf_getscn(elf, section))) {
       
    38 	return NULL;
       
    39     }
       
    40     if (scn->s_index == SHN_UNDEF) {
       
    41 	seterr(ERROR_NOSTRTAB);
       
    42 	return NULL;
       
    43     }
       
    44     /*
       
    45      * checking the section header is more appropriate
       
    46      */
       
    47     if (elf->e_class == ELFCLASS32) {
       
    48 	if (scn->s_shdr32.sh_type != SHT_STRTAB) {
       
    49 	    seterr(ERROR_NOSTRTAB);
       
    50 	    return NULL;
       
    51 	}
       
    52     }
       
    53 #if __LIBELF64
       
    54     else if (elf->e_class == ELFCLASS64) {
       
    55 	if (scn->s_shdr64.sh_type != SHT_STRTAB) {
       
    56 	    seterr(ERROR_NOSTRTAB);
       
    57 	    return NULL;
       
    58 	}
       
    59     }
       
    60 #endif /* __LIBELF64 */
       
    61     else if (valid_class(elf->e_class)) {
       
    62 	seterr(ERROR_UNIMPLEMENTED);
       
    63 	return NULL;
       
    64     }
       
    65     else {
       
    66 	seterr(ERROR_UNKNOWN_CLASS);
       
    67 	return NULL;
       
    68     }
       
    69     /*
       
    70      * Find matching buffer
       
    71      */
       
    72     n = 0;
       
    73     data = NULL;
       
    74     if (elf->e_elf_flags & ELF_F_LAYOUT) {
       
    75 	/*
       
    76 	 * Programmer is responsible for d_off
       
    77 	 * Note: buffers may be in any order!
       
    78 	 */
       
    79 	while ((data = elf_getdata(scn, data))) {
       
    80 	    n = data->d_off;
       
    81 	    if (offset >= n && offset - n < data->d_size) {
       
    82 		/*
       
    83 		 * Found it
       
    84 		 */
       
    85 		break;
       
    86 	    }
       
    87 	}
       
    88     }
       
    89     else {
       
    90 	/*
       
    91 	 * Calculate offsets myself
       
    92 	 */
       
    93 	while ((data = elf_getdata(scn, data))) {
       
    94 	    if (data->d_align > 1) {
       
    95 		n += data->d_align - 1;
       
    96 		n -= n % data->d_align;
       
    97 	    }
       
    98 	    if (offset < n) {
       
    99 		/*
       
   100 		 * Invalid offset: points into a hole
       
   101 		 */
       
   102 		seterr(ERROR_BADSTROFF);
       
   103 		return NULL;
       
   104 	    }
       
   105 	    if (offset - n < data->d_size) {
       
   106 		/*
       
   107 		 * Found it
       
   108 		 */
       
   109 		break;
       
   110 	    }
       
   111 	    n += data->d_size;
       
   112 	}
       
   113     }
       
   114     if (data == NULL) {
       
   115 	/*
       
   116 	 * Not found
       
   117 	 */
       
   118 	seterr(ERROR_BADSTROFF);
       
   119 	return NULL;
       
   120     }
       
   121     if (data->d_buf == NULL) {
       
   122 	/*
       
   123 	 * Buffer is NULL (usually the programmers' fault)
       
   124 	 */
       
   125 	seterr(ERROR_NULLBUF);
       
   126 	return NULL;
       
   127     }
       
   128     offset -= n;
       
   129     s = (char*)data->d_buf;
       
   130     if (!(_elf_sanity_checks & SANITY_CHECK_STRPTR)) {
       
   131 	return s + offset;
       
   132     }
       
   133     /*
       
   134      * Perform extra sanity check
       
   135      */
       
   136     for (n = offset; n < data->d_size; n++) {
       
   137 	if (s[n] == '\0') {
       
   138 	    /*
       
   139 	     * Return properly NUL terminated string
       
   140 	     */
       
   141 	    return s + offset;
       
   142 	}
       
   143     }
       
   144     /*
       
   145      * String is not NUL terminated
       
   146      * Return error to avoid SEGV in application
       
   147      */
       
   148     seterr(ERROR_UNTERM);
       
   149     return NULL;
       
   150 }