xref: /aosp_15_r20/external/elfutils/libasm/asm_addsleb128.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Add signed little endian base 128 integer to a section.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2002, 2005 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker    This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker    Written by Ulrich Drepper <[email protected]>, 2002.
5*7304104dSAndroid Build Coastguard Worker 
6*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
7*7304104dSAndroid Build Coastguard Worker    it under the terms of either
8*7304104dSAndroid Build Coastguard Worker 
9*7304104dSAndroid Build Coastguard Worker      * the GNU Lesser General Public License as published by the Free
10*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 3 of the License, or (at
11*7304104dSAndroid Build Coastguard Worker        your option) any later version
12*7304104dSAndroid Build Coastguard Worker 
13*7304104dSAndroid Build Coastguard Worker    or
14*7304104dSAndroid Build Coastguard Worker 
15*7304104dSAndroid Build Coastguard Worker      * the GNU General Public License as published by the Free
16*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 2 of the License, or (at
17*7304104dSAndroid Build Coastguard Worker        your option) any later version
18*7304104dSAndroid Build Coastguard Worker 
19*7304104dSAndroid Build Coastguard Worker    or both in parallel, as here.
20*7304104dSAndroid Build Coastguard Worker 
21*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
22*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
23*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24*7304104dSAndroid Build Coastguard Worker    General Public License for more details.
25*7304104dSAndroid Build Coastguard Worker 
26*7304104dSAndroid Build Coastguard Worker    You should have received copies of the GNU General Public License and
27*7304104dSAndroid Build Coastguard Worker    the GNU Lesser General Public License along with this program.  If
28*7304104dSAndroid Build Coastguard Worker    not, see <http://www.gnu.org/licenses/>.  */
29*7304104dSAndroid Build Coastguard Worker 
30*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
31*7304104dSAndroid Build Coastguard Worker # include <config.h>
32*7304104dSAndroid Build Coastguard Worker #endif
33*7304104dSAndroid Build Coastguard Worker 
34*7304104dSAndroid Build Coastguard Worker #include <inttypes.h>
35*7304104dSAndroid Build Coastguard Worker #include <string.h>
36*7304104dSAndroid Build Coastguard Worker 
37*7304104dSAndroid Build Coastguard Worker #include <libasmP.h>
38*7304104dSAndroid Build Coastguard Worker 
39*7304104dSAndroid Build Coastguard Worker 
40*7304104dSAndroid Build Coastguard Worker int
asm_addsleb128(AsmScn_t * asmscn,int32_t num)41*7304104dSAndroid Build Coastguard Worker asm_addsleb128 (AsmScn_t *asmscn, int32_t num)
42*7304104dSAndroid Build Coastguard Worker {
43*7304104dSAndroid Build Coastguard Worker   if (asmscn == NULL)
44*7304104dSAndroid Build Coastguard Worker     return -1;
45*7304104dSAndroid Build Coastguard Worker 
46*7304104dSAndroid Build Coastguard Worker   if (asmscn->type == SHT_NOBITS && unlikely (num != 0))
47*7304104dSAndroid Build Coastguard Worker     {
48*7304104dSAndroid Build Coastguard Worker       __libasm_seterrno (ASM_E_TYPE);
49*7304104dSAndroid Build Coastguard Worker       return -1;
50*7304104dSAndroid Build Coastguard Worker     }
51*7304104dSAndroid Build Coastguard Worker 
52*7304104dSAndroid Build Coastguard Worker   if (unlikely (asmscn->ctx->textp))
53*7304104dSAndroid Build Coastguard Worker     fprintf (asmscn->ctx->out.file, "\t.sleb128\t%" PRId32 "\n", num);
54*7304104dSAndroid Build Coastguard Worker   else
55*7304104dSAndroid Build Coastguard Worker     {
56*7304104dSAndroid Build Coastguard Worker       char tmpbuf[(sizeof (num) * 8 + 6) / 7];
57*7304104dSAndroid Build Coastguard Worker       char *dest = tmpbuf;
58*7304104dSAndroid Build Coastguard Worker       uint32_t byte;
59*7304104dSAndroid Build Coastguard Worker       int32_t endval = num >> 31;
60*7304104dSAndroid Build Coastguard Worker 
61*7304104dSAndroid Build Coastguard Worker       if (num == 0)
62*7304104dSAndroid Build Coastguard Worker 	byte = 0;
63*7304104dSAndroid Build Coastguard Worker       else
64*7304104dSAndroid Build Coastguard Worker 	while (1)
65*7304104dSAndroid Build Coastguard Worker 	  {
66*7304104dSAndroid Build Coastguard Worker 	    byte = num & 0x7f;
67*7304104dSAndroid Build Coastguard Worker 
68*7304104dSAndroid Build Coastguard Worker 	    num >>= 7;
69*7304104dSAndroid Build Coastguard Worker 	    if (num == endval)
70*7304104dSAndroid Build Coastguard Worker 	      /* This is the last byte.  */
71*7304104dSAndroid Build Coastguard Worker 	      break;
72*7304104dSAndroid Build Coastguard Worker 
73*7304104dSAndroid Build Coastguard Worker 	    *dest++ = byte | 0x80;
74*7304104dSAndroid Build Coastguard Worker 	  }
75*7304104dSAndroid Build Coastguard Worker 
76*7304104dSAndroid Build Coastguard Worker       *dest++ = byte;
77*7304104dSAndroid Build Coastguard Worker 
78*7304104dSAndroid Build Coastguard Worker       /* Number of bytes produced.  */
79*7304104dSAndroid Build Coastguard Worker       size_t nbytes = dest - tmpbuf;
80*7304104dSAndroid Build Coastguard Worker 
81*7304104dSAndroid Build Coastguard Worker       /* Make sure we have enough room.  */
82*7304104dSAndroid Build Coastguard Worker       if (__libasm_ensure_section_space (asmscn, nbytes) != 0)
83*7304104dSAndroid Build Coastguard Worker 	return -1;
84*7304104dSAndroid Build Coastguard Worker 
85*7304104dSAndroid Build Coastguard Worker       /* Copy the bytes.  */
86*7304104dSAndroid Build Coastguard Worker       if (likely (asmscn->type != SHT_NOBITS))
87*7304104dSAndroid Build Coastguard Worker 	memcpy (&asmscn->content->data[asmscn->content->len], tmpbuf, nbytes);
88*7304104dSAndroid Build Coastguard Worker 
89*7304104dSAndroid Build Coastguard Worker       /* Adjust the pointer in the data buffer.  */
90*7304104dSAndroid Build Coastguard Worker       asmscn->content->len += nbytes;
91*7304104dSAndroid Build Coastguard Worker 
92*7304104dSAndroid Build Coastguard Worker       /* Increment the offset in the (sub)section.  */
93*7304104dSAndroid Build Coastguard Worker       asmscn->offset += nbytes;
94*7304104dSAndroid Build Coastguard Worker     }
95*7304104dSAndroid Build Coastguard Worker 
96*7304104dSAndroid Build Coastguard Worker   return 0;
97*7304104dSAndroid Build Coastguard Worker }
98