tools/elf4rom/libs/dwarf-20071209/libdwarf/dwarf_leb.c
changeset 34 92d87f2e53c2
equal deleted inserted replaced
33:1af5c1be89f8 34:92d87f2e53c2
       
     1 /*
       
     2 
       
     3   Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
       
     4 
       
     5   This program is free software; you can redistribute it and/or modify it
       
     6   under the terms of version 2.1 of the GNU Lesser General Public License 
       
     7   as published by the Free Software Foundation.
       
     8 
       
     9   This program is distributed in the hope that it would be useful, but
       
    10   WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
       
    12 
       
    13   Further, this software is distributed without any warranty that it is
       
    14   free of the rightful claim of any third person regarding infringement 
       
    15   or the like.  Any license provided herein, whether implied or 
       
    16   otherwise, applies only to this software file.  Patent licenses, if
       
    17   any, provided herein do not apply to combinations of this program with 
       
    18   other software, or any other product whatsoever.  
       
    19 
       
    20   You should have received a copy of the GNU Lesser General Public 
       
    21   License along with this program; if not, write the Free Software 
       
    22   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
       
    23   USA.
       
    24 
       
    25   Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
       
    26   Mountain View, CA 94043, or:
       
    27 
       
    28   http://www.sgi.com
       
    29 
       
    30   For further information regarding this notice, see:
       
    31 
       
    32   http://oss.sgi.com/projects/GenInfo/NoticeExplan
       
    33 
       
    34 */
       
    35 
       
    36 
       
    37 
       
    38 #include "config.h"
       
    39 #include "dwarf_incl.h"
       
    40 #include <stdio.h>
       
    41 
       
    42 
       
    43 /*
       
    44     decode ULEB
       
    45 */
       
    46 Dwarf_Unsigned
       
    47 _dwarf_decode_u_leb128(Dwarf_Small * leb128, Dwarf_Word * leb128_length)
       
    48 {
       
    49     unsigned char byte;
       
    50     Dwarf_Word word_number;
       
    51     Dwarf_Unsigned number;
       
    52     Dwarf_Sword shift;
       
    53     Dwarf_Sword byte_length;
       
    54 
       
    55     /* The following unrolls-the-loop for the first few bytes and
       
    56        unpacks into 32 bits to make this as fast as possible.
       
    57        word_number is assumed big enough that the shift has a defined
       
    58        result. */
       
    59     if ((*leb128 & 0x80) == 0) {
       
    60 	if (leb128_length != NULL)
       
    61 	    *leb128_length = 1;
       
    62 	return (*leb128);
       
    63     } else if ((*(leb128 + 1) & 0x80) == 0) {
       
    64 	if (leb128_length != NULL)
       
    65 	    *leb128_length = 2;
       
    66 
       
    67 	word_number = *leb128 & 0x7f;
       
    68 	word_number |= (*(leb128 + 1) & 0x7f) << 7;
       
    69 	return (word_number);
       
    70     } else if ((*(leb128 + 2) & 0x80) == 0) {
       
    71 	if (leb128_length != NULL)
       
    72 	    *leb128_length = 3;
       
    73 
       
    74 	word_number = *leb128 & 0x7f;
       
    75 	word_number |= (*(leb128 + 1) & 0x7f) << 7;
       
    76 	word_number |= (*(leb128 + 2) & 0x7f) << 14;
       
    77 	return (word_number);
       
    78     } else if ((*(leb128 + 3) & 0x80) == 0) {
       
    79 	if (leb128_length != NULL)
       
    80 	    *leb128_length = 4;
       
    81 
       
    82 	word_number = *leb128 & 0x7f;
       
    83 	word_number |= (*(leb128 + 1) & 0x7f) << 7;
       
    84 	word_number |= (*(leb128 + 2) & 0x7f) << 14;
       
    85 	word_number |= (*(leb128 + 3) & 0x7f) << 21;
       
    86 	return (word_number);
       
    87     }
       
    88 
       
    89     /* The rest handles long numbers Because the 'number' may be larger 
       
    90        than the default int/unsigned, we must cast the 'byte' before
       
    91        the shift for the shift to have a defined result. */
       
    92     number = 0;
       
    93     shift = 0;
       
    94     byte_length = 1;
       
    95     byte = *(leb128);
       
    96     for (;;) {
       
    97 	number |= ((Dwarf_Unsigned) (byte & 0x7f)) << shift;
       
    98 
       
    99 	if ((byte & 0x80) == 0) {
       
   100 	    if (leb128_length != NULL)
       
   101 		*leb128_length = byte_length;
       
   102 	    return (number);
       
   103 	}
       
   104 	shift += 7;
       
   105 
       
   106 	byte_length++;
       
   107 	++leb128;
       
   108 	byte = *leb128;
       
   109     }
       
   110 }
       
   111 
       
   112 #define BITSINBYTE 8
       
   113 
       
   114 /*
       
   115     decode SLEB
       
   116 */
       
   117 Dwarf_Signed
       
   118 _dwarf_decode_s_leb128(Dwarf_Small * leb128, Dwarf_Word * leb128_length)
       
   119 {
       
   120     Dwarf_Signed number = 0;
       
   121     Dwarf_Bool sign = 0;
       
   122     Dwarf_Sword shift = 0;
       
   123     unsigned char byte = *leb128;
       
   124     Dwarf_Sword byte_length = 1;
       
   125 
       
   126     /* byte_length being the number of bytes of data absorbed so far in 
       
   127        turning the leb into a Dwarf_Signed. */
       
   128 
       
   129     for (;;) {
       
   130 	sign = byte & 0x40;
       
   131 	number |= ((Dwarf_Signed) ((byte & 0x7f))) << shift;
       
   132 	shift += 7;
       
   133 
       
   134 	if ((byte & 0x80) == 0) {
       
   135 	    break;
       
   136 	}
       
   137 	++leb128;
       
   138 	byte = *leb128;
       
   139 	byte_length++;
       
   140     }
       
   141 
       
   142     if ((shift < sizeof(Dwarf_Signed) * BITSINBYTE) && sign) {
       
   143 	number |= -((Dwarf_Signed) 1 << shift);
       
   144     }
       
   145 
       
   146     if (leb128_length != NULL)
       
   147 	*leb128_length = byte_length;
       
   148     return (number);
       
   149 }