1 /* Copyright (C) 2001, 2002 Red Hat, Inc.
2 Written by Jakub Jelinek <jakub@redhat.com>, 2001.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 #define UREAD(le,nn) \
23 read_u##le##nn (DSO *dso, GElf_Addr addr) \
25 unsigned char *data = get_data (dso, addr, NULL); \
30 return buf_read_u##le##nn (data); \
33 #define WRITE(le,nn) \
35 write_##le##nn (DSO *dso, GElf_Addr addr, uint##nn##_t val) \
38 unsigned char *data = get_data (dso, addr, &sec); \
43 buf_write_##le##nn (data, val); \
44 elf_flagscn (dso->scn[sec], ELF_C_SET, ELF_F_DIRTY); \
48 #define BUFREADUNE(nn) \
50 buf_read_une##nn (DSO *dso, unsigned char *buf) \
52 if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) \
53 return buf_read_ule32 (buf); \
55 return buf_read_ube32 (buf); \
60 read_une##nn (DSO *dso, GElf_Addr addr) \
62 if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) \
63 return read_ule##nn (dso, addr); \
65 return read_ube##nn (dso, addr); \
70 write_ne##nn (DSO *dso, GElf_Addr addr, uint##nn##_t val) \
72 if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) \
73 write_le##nn (dso, addr, val); \
75 write_be##nn (dso, addr, val); \
78 #define BUFWRITENE(nn) \
80 buf_write_ne##nn (DSO *dso, unsigned char *buf, \
83 if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) \
84 buf_write_le##nn (buf, val); \
86 buf_write_be##nn (buf, val); \
89 #define READWRITE(le,nn) UREAD(le,nn) WRITE(le,nn)
90 #define READWRITESIZE(nn) \
91 READWRITE(le,nn) READWRITE(be,nn) \
92 BUFREADUNE(nn) READUNE(nn) \
93 WRITENE(nn) BUFWRITENE(nn)
96 get_data (DSO *dso, GElf_Addr addr, int *secp)
98 int sec = addr_to_sec (dso, addr);
99 Elf_Data *data = NULL;
107 addr -= dso->shdr[sec].sh_addr;
108 while ((data = elf_getdata (dso->scn[sec], data)) != NULL)
109 if (data->d_off <= addr && data->d_off + data->d_size > addr)
110 return (unsigned char *) data->d_buf + (addr - data->d_off);
115 /* Initialize IT so that the first byte it provides is address ADDR
119 init_data_iterator (struct data_iterator *it, DSO *dso, GElf_Addr addr)
126 /* Return a pointer to the next SIZE bytes pointed to by IT, and move
127 IT to the end of the returned block. Return null if the data could
128 not be read for some reason. */
131 get_data_from_iterator (struct data_iterator *it, GElf_Addr size)
135 /* If we're at the end of a data block, move onto the next. */
136 if (it->data && it->data->d_off + it->data->d_size == it->sec_offset)
137 it->data = elf_getdata (it->dso->scn[it->sec], it->data);
139 if (it->data == NULL)
141 /* Find out which section contains the next byte. */
142 it->sec = addr_to_sec (it->dso, it->addr);
146 /* Fast-forward to the block that contains ADDR, if any. */
147 it->sec_offset = it->addr - it->dso->shdr[it->sec].sh_addr;
149 it->data = elf_getdata (it->dso->scn[it->sec], it->data);
150 while (it->data && it->data->d_off + it->data->d_size <= it->sec_offset);
153 /* Make sure that all the data we want is included in this block. */
155 || it->data->d_off > it->sec_offset
156 || it->data->d_off + it->data->d_size < it->sec_offset + size)
159 ptr = (unsigned char *) it->data->d_buf + (it->sec_offset - it->data->d_off);
160 it->sec_offset += size;
165 /* Read the symbol pointed to by IT into SYM and move IT onto the
166 next symbol. Return true on success. */
169 get_sym_from_iterator (struct data_iterator *it, GElf_Sym *sym)
171 GElf_Addr offset, size;
174 size = gelf_fsize (it->dso->elf, ELF_T_SYM, 1, EV_CURRENT);
175 ptr = get_data_from_iterator (it, size);
178 offset = ptr - (unsigned char *) it->data->d_buf;
179 if (offset % size == 0)
181 gelfx_getsym (it->dso->elf, it->data, offset / size, sym);
189 buf_read_u8 (unsigned char *data)
195 buf_read_ule16 (unsigned char *data)
197 return data[0] | (data[1] << 8);
201 buf_read_ube16 (unsigned char *data)
203 return data[1] | (data[0] << 8);
207 buf_read_ule32 (unsigned char *data)
209 return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
213 buf_read_ube32 (unsigned char *data)
215 return data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24);
219 buf_read_ule64 (unsigned char *data)
221 return (data[0] | (data[1] << 8) | (data[2] << 16))
222 | (((uint64_t)data[3]) << 24)
223 | (((uint64_t)data[4]) << 32)
224 | (((uint64_t)data[5]) << 40)
225 | (((uint64_t)data[6]) << 48)
226 | (((uint64_t)data[7]) << 56);
230 buf_read_ube64 (unsigned char *data)
232 return (data[7] | (data[6] << 8) | (data[5] << 16))
233 | (((uint64_t)data[4]) << 24)
234 | (((uint64_t)data[3]) << 32)
235 | (((uint64_t)data[2]) << 40)
236 | (((uint64_t)data[1]) << 48)
237 | (((uint64_t)data[0]) << 56);
241 buf_write_8 (unsigned char *data, uint8_t val)
247 buf_write_le16 (unsigned char *data, uint16_t val)
254 buf_write_be16 (unsigned char *data, uint16_t val)
261 buf_write_le32 (unsigned char *data, uint32_t val)
270 buf_write_be32 (unsigned char *data, uint32_t val)
279 buf_write_le64 (unsigned char *data, uint64_t val)
292 buf_write_be64 (unsigned char *data, uint64_t val)
310 strptr (DSO *dso, int sec, off_t offset)
316 if (offset >= 0 && offset < dso->shdr[sec].sh_size)
319 while ((data = elf_getdata (scn, data)) != NULL)
322 && offset >= data->d_off
323 && offset < data->d_off + data->d_size)
324 return (const char *) data->d_buf + (offset - data->d_off);