1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
|
/* Copyright (C) 2001, 2005, 2006 Red Hat, Inc.
Written by Jakub Jelinek <jakub@redhat.com>, 2001.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <config.h>
#include <assert.h>
#include <byteswap.h>
#include <endian.h>
#include <error.h>
#include "prelink.h"
#define N_ZERO 0x00
#define N_GSYM 0x20
#define N_FNAME 0x22
#define N_FUN 0x24
#define N_STSYM 0x26
#define N_LCSYM 0x28
#define N_MAIN 0x2a
#define N_BNSYM 0x2e
#define N_PC 0x30
#define N_NSYMS 0x32
#define N_NOMAP 0x34
#define N_OBJ 0x38
#define N_OPT 0x3c
#define N_RSYM 0x40
#define N_M2C 0x42
#define N_SLINE 0x44
#define N_DSLINE 0x46
#define N_BSLINE 0x48
#define N_BROWS 0x48
#define N_DEFD 0x4a
#define N_ENSYM 0x4e
#define N_EHDECL 0x50
#define N_MOD2 0x50
#define N_CATCH 0x54
#define N_SSYM 0x60
#define N_SO 0x64
#define N_LSYM 0x80
#define N_BINCL 0x82
#define N_SOL 0x84
#define N_PSYM 0xa0
#define N_EINCL 0xa2
#define N_ENTRY 0xa4
#define N_LBRAC 0xc0
#define N_EXCL 0xc2
#define N_SCOPE 0xc4
#define N_RBRAC 0xe0
#define N_BCOMM 0xe2
#define N_ECOMM 0xe4
#define N_ECOML 0xe8
#define N_LENG 0xfe
static uint32_t
read_native (char *p)
{
return *(uint32_t *)p;
}
static uint32_t
read_swap (char *p)
{
return bswap_32 (*(uint32_t *)p);
}
static void
write_native (char *p, uint32_t v)
{
*(uint32_t *)p = v;
}
static void
write_swap (char *p, uint32_t v)
{
*(uint32_t *)p = bswap_32 (v);
}
int
adjust_stabs (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust)
{
Elf_Data *data = NULL;
Elf_Scn *scn = dso->scn[n];
off_t off;
uint32_t (*read_32) (char *p);
void (*write_32) (char *p, uint32_t v);
uint32_t value;
int sec, type;
assert (dso->shdr[n].sh_entsize == 12);
data = elf_getdata (scn, NULL);
assert (data != NULL && data->d_buf != NULL);
assert (elf_getdata (scn, data) == NULL);
assert (data->d_off == 0 && data->d_size == dso->shdr[n].sh_size);
#if __BYTE_ORDER == __BIG_ENDIAN
if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
#elif __BYTE_ORDER == __LITTLE_ENDIAN
if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
#else
# error Not supported host endianess
#endif
{
read_32 = read_native;
write_32 = write_native;
}
#if __BYTE_ORDER == __BIG_ENDIAN
else if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
#elif __BYTE_ORDER == __LITTLE_ENDIAN
else if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
#endif
{
read_32 = read_swap;
write_32 = write_swap;
}
else
{
error (0, 0, "%s: Wrong ELF data enconding", dso->filename);
return 1;
}
for (off = 0; off < data->d_size; off += 12)
{
switch ((type = *(uint8_t *)(data->d_buf + off + 4)))
{
case N_FUN:
/* If string is "", N_FUN is function length, otherwise
it is function start address. */
if (read_32 (data->d_buf + off) == 0)
break;
/* FALLTHROUGH */
case N_STSYM:
case N_LCSYM:
case N_CATCH:
case N_SO:
case N_SOL:
case N_BNSYM:
case N_ENSYM:
value = read_32 (data->d_buf + off + 8);
sec = addr_to_sec (dso, value);
if (sec != -1)
{
addr_adjust (value, start, adjust);
write_32 (data->d_buf + off + 8, value);
}
break;
/* These should be always 0. */
case N_GSYM:
case N_BINCL:
case N_EINCL:
case N_EXCL:
case N_BCOMM:
case N_ECOMM:
/* These contain other values. */
case N_ZERO:
case N_NSYMS:
case N_NOMAP:
case N_RSYM:
case N_LSYM:
case N_PSYM:
case N_OPT:
/* These are relative. */
case N_LBRAC:
case N_RBRAC:
case N_SLINE:
case N_BSLINE:
case N_DSLINE:
break;
default:
error (0, 0, "%s: Unknown stabs code 0x%02x\n", dso->filename, type);
return 1;
}
}
elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY);
return 0;
}
|