149d3bc91SRichard Lowe /*
249d3bc91SRichard Lowe 
307dc1947SRichard Lowe   Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
4*4d9fdb46SRobert Mustacchi   Portions Copyright 2011 David Anderson.  All Rights Reserved.
549d3bc91SRichard Lowe 
649d3bc91SRichard Lowe   This program is free software; you can redistribute it and/or modify it
7*4d9fdb46SRobert Mustacchi   under the terms of version 2.1 of the GNU Lesser General Public License
849d3bc91SRichard Lowe   as published by the Free Software Foundation.
949d3bc91SRichard Lowe 
1049d3bc91SRichard Lowe   This program is distributed in the hope that it would be useful, but
1149d3bc91SRichard Lowe   WITHOUT ANY WARRANTY; without even the implied warranty of
1349d3bc91SRichard Lowe 
1449d3bc91SRichard Lowe   Further, this software is distributed without any warranty that it is
15*4d9fdb46SRobert Mustacchi   free of the rightful claim of any third person regarding infringement
16*4d9fdb46SRobert Mustacchi   or the like.  Any license provided herein, whether implied or
1749d3bc91SRichard Lowe   otherwise, applies only to this software file.  Patent licenses, if
18*4d9fdb46SRobert Mustacchi   any, provided herein do not apply to combinations of this program with
19*4d9fdb46SRobert Mustacchi   other software, or any other product whatsoever.
2049d3bc91SRichard Lowe 
21*4d9fdb46SRobert Mustacchi   You should have received a copy of the GNU Lesser General Public
22*4d9fdb46SRobert Mustacchi   License along with this program; if not, write the Free Software
2307dc1947SRichard Lowe   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
2449d3bc91SRichard Lowe   USA.
2549d3bc91SRichard Lowe 
2649d3bc91SRichard Lowe */
2749d3bc91SRichard Lowe 
2849d3bc91SRichard Lowe #include "config.h"
2949d3bc91SRichard Lowe #include "libdwarfdefs.h"
3049d3bc91SRichard Lowe #include <string.h>
31*4d9fdb46SRobert Mustacchi #include "dwarf.h"
32*4d9fdb46SRobert Mustacchi #include "libdwarf.h"
33*4d9fdb46SRobert Mustacchi #include "pro_encode_nm.h"
3449d3bc91SRichard Lowe 
3549d3bc91SRichard Lowe #define MORE_BYTES      0x80
3649d3bc91SRichard Lowe #define DATA_MASK       0x7f
3749d3bc91SRichard Lowe #define DIGIT_WIDTH     7
3849d3bc91SRichard Lowe #define SIGN_BIT        0x40
3949d3bc91SRichard Lowe 
4049d3bc91SRichard Lowe 
41*4d9fdb46SRobert Mustacchi /*  Encode val as a leb128. This encodes it as an unsigned
42*4d9fdb46SRobert Mustacchi     number. */
43*4d9fdb46SRobert Mustacchi /*  Return DW_DLV_ERROR or DW_DLV_OK.
44*4d9fdb46SRobert Mustacchi     space to write leb number is provided by caller, with caller
45*4d9fdb46SRobert Mustacchi     passing length.
46*4d9fdb46SRobert Mustacchi     number of bytes used returned thru nbytes arg */
4749d3bc91SRichard Lowe int
_dwarf_pro_encode_leb128_nm(Dwarf_Unsigned val,int * nbytes,char * space,int splen)4849d3bc91SRichard Lowe _dwarf_pro_encode_leb128_nm(Dwarf_Unsigned val, int *nbytes,
49*4d9fdb46SRobert Mustacchi     char *space, int splen)
5049d3bc91SRichard Lowe {
5149d3bc91SRichard Lowe     char *a;
5249d3bc91SRichard Lowe     char *end = space + splen;
5349d3bc91SRichard Lowe 
5449d3bc91SRichard Lowe     a = space;
5549d3bc91SRichard Lowe     do {
5607dc1947SRichard Lowe         unsigned char uc;
5707dc1947SRichard Lowe 
5807dc1947SRichard Lowe         if (a >= end) {
5907dc1947SRichard Lowe             return DW_DLV_ERROR;
6007dc1947SRichard Lowe         }
6107dc1947SRichard Lowe         uc = val & DATA_MASK;
6207dc1947SRichard Lowe         val >>= DIGIT_WIDTH;
6307dc1947SRichard Lowe         if (val != 0) {
6407dc1947SRichard Lowe             uc |= MORE_BYTES;
6507dc1947SRichard Lowe         }
6607dc1947SRichard Lowe         *a = uc;
6707dc1947SRichard Lowe         a++;
6849d3bc91SRichard Lowe     } while (val);
69*4d9fdb46SRobert Mustacchi     *nbytes = (int)(a - space);
7049d3bc91SRichard Lowe     return DW_DLV_OK;
7149d3bc91SRichard Lowe }
7249d3bc91SRichard Lowe 
7349d3bc91SRichard Lowe /* return DW_DLV_ERROR or DW_DLV_OK.
7449d3bc91SRichard Lowe ** space to write leb number is provided by caller, with caller
7549d3bc91SRichard Lowe ** passing length.
7649d3bc91SRichard Lowe ** number of bytes used returned thru nbytes arg
7749d3bc91SRichard Lowe ** encodes a signed number.
7849d3bc91SRichard Lowe */
7949d3bc91SRichard Lowe int
_dwarf_pro_encode_signed_leb128_nm(Dwarf_Signed value,int * nbytes,char * space,int splen)8049d3bc91SRichard Lowe _dwarf_pro_encode_signed_leb128_nm(Dwarf_Signed value, int *nbytes,
81*4d9fdb46SRobert Mustacchi     char *space, int splen)
8249d3bc91SRichard Lowe {
8349d3bc91SRichard Lowe     char *str;
8449d3bc91SRichard Lowe     Dwarf_Signed sign = -(value < 0);
8549d3bc91SRichard Lowe     int more = 1;
8649d3bc91SRichard Lowe     char *end = space + splen;
8749d3bc91SRichard Lowe 
8849d3bc91SRichard Lowe     str = space;
8949d3bc91SRichard Lowe 
9049d3bc91SRichard Lowe     do {
9107dc1947SRichard Lowe         unsigned char byte = value & DATA_MASK;
9207dc1947SRichard Lowe 
9307dc1947SRichard Lowe         value >>= DIGIT_WIDTH;
9407dc1947SRichard Lowe 
9507dc1947SRichard Lowe         if (str >= end) {
9607dc1947SRichard Lowe             return DW_DLV_ERROR;
9707dc1947SRichard Lowe         }
98*4d9fdb46SRobert Mustacchi         /*  Remaining chunks would just contain the sign bit, and this chunk
99*4d9fdb46SRobert Mustacchi             has already captured at least one sign bit.  */
10007dc1947SRichard Lowe         if (value == sign && ((byte & SIGN_BIT) == (sign & SIGN_BIT))) {
10107dc1947SRichard Lowe             more = 0;
10207dc1947SRichard Lowe         } else {
10307dc1947SRichard Lowe             byte |= MORE_BYTES;
10407dc1947SRichard Lowe         }
10507dc1947SRichard Lowe         *str = byte;
10607dc1947SRichard Lowe         str++;
10749d3bc91SRichard Lowe     } while (more);
108*4d9fdb46SRobert Mustacchi     *nbytes = (int)(str - space);
10949d3bc91SRichard Lowe     return DW_DLV_OK;
11049d3bc91SRichard Lowe }