ROSE
0.9.6a
Main Page
Related Pages
Modules
Namespaces
Classes
Files
Examples
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Friends
Macros
Groups
Pages
ElfStringTable.C
Go to the documentation of this file.
1
/* ELF String Tables
2
*
3
* String tables are represented with two main classes:
4
*
5
* SgAsmElfStringSection is an SgAsmElfSection that contains a string table. It points to an SgAsmElfStrtab.
6
*
7
* SgAsmElfStrtab is a class representing the string table contained in an SgAsmElfStringSection. It inherits from
8
* SgAsmGenericStrtab. An SgAsmElfStrtab points back to the SgAsmElfStringSection that contains it.
9
*/
10
11
#include "
sage3basic.h
"
12
14
void
15
SgAsmElfStringSection::ctor
()
16
{
17
get_name
()->
set_string
(
"ELF String Table"
);
18
if
(
get_size
()==0)
19
set_size
(1);
20
p_strtab
=
new
SgAsmElfStrtab
(
this
);
21
}
22
24
SgAsmElfStringSection
*
25
SgAsmElfStringSection::parse
()
26
{
27
SgAsmElfSection::parse
();
28
ROSE_ASSERT(
p_strtab
);
29
p_strtab
->
get_freelist
().
clear
();
/*because set_size() during construction added to the free list*/
30
p_strtab
->
parse
();
31
return
this
;
32
}
33
38
bool
39
SgAsmElfStringSection::reallocate
()
40
{
41
bool
reallocated =
SgAsmElfSection::reallocate
();
42
if
(
get_strtab
()->
reallocate
(
false
))
43
reallocated =
true
;
44
45
/* Update parts of the section and segment tables not updated by superclass */
46
SgAsmElfSectionTableEntry
*secent =
get_section_entry
();
47
if
(secent)
48
secent->
set_sh_type
(
SgAsmElfSectionTableEntry::SHT_STRTAB
);
49
50
return
reallocated;
51
}
52
54
void
55
SgAsmElfStringSection::unparse
(std::ostream &f)
const
56
{
57
get_strtab
()->
unparse
(f);
58
unparse_holes
(f);
59
}
60
63
void
64
SgAsmElfStringSection::set_size
(
rose_addr_t
newsize)
65
{
66
rose_addr_t
orig_size =
get_size
();
67
SgAsmElfSection::set_size
(newsize);
68
SgAsmGenericStrtab
*strtab =
get_strtab
();
69
70
if
(strtab) {
71
if
(
get_size
() > orig_size) {
72
/* Add new address space to string table free list */
73
rose_addr_t
n =
get_size
() - orig_size;
74
strtab->
get_freelist
().
insert
(
Extent
(orig_size, n));
75
}
else
if
(
get_size
() < orig_size) {
76
/* Remove deleted address space from string table free list */
77
rose_addr_t
n = orig_size -
get_size
();
78
strtab->
get_freelist
().
erase
(
Extent
(
get_size
(), n));
79
}
80
}
81
}
82
84
void
85
SgAsmElfStringSection::dump
(FILE *f,
const
char
*
prefix
, ssize_t idx)
const
86
{
87
char
p[4096];
88
if
(idx>=0) {
89
sprintf(p,
"%sElfStringSection[%zd]."
, prefix, idx);
90
}
else
{
91
sprintf(p,
"%sElfStringSection."
, prefix);
92
}
93
94
SgAsmElfSection::dump
(f, p, -1);
95
96
ROSE_ASSERT(
get_strtab
()!=NULL);
97
get_strtab
()->
dump
(f, p, -1);
98
99
if
(
variantT
() ==
V_SgAsmElfStringSection
)
//unless a base class
100
hexdump
(f, 0, std::string(p)+
"data at "
,
p_data
);
101
}
102
103
105
void
106
SgAsmElfStrtab::ctor
()
107
{
108
ROSE_ASSERT(
get_container
());
109
if
(
get_container
()->get_size()==0)
110
get_container
()->
set_size
(1);
111
p_dont_free
=
create_storage
(0,
false
);
112
}
113
116
SgAsmElfStrtab
*
117
SgAsmElfStrtab::parse
()
118
{
119
SgAsmGenericStrtab::parse
();
120
ROSE_ASSERT(
get_container
());
121
if
(
get_container
()->get_size()>0) {
122
unsigned
char
first_byte;
123
get_container
()->
read_content_local
(0, &first_byte, 1);
124
if
(first_byte==
'\0'
) {
125
if
(
p_dont_free
) {
126
ROSE_ASSERT(0==
p_dont_free
->
get_offset
());
127
}
else
{
128
p_dont_free
=
create_storage
(0,
false
);
129
}
130
}
else
if
(
p_dont_free
) {
131
p_dont_free
= NULL;
132
}
133
}
134
return
this
;
135
}
136
141
SgAsmElfStrtab::~SgAsmElfStrtab
()
142
{
143
for
(referenced_t::iterator i =
p_storage_list
.begin(); i !=
p_storage_list
.end(); ++i) {
144
SgAsmStringStorage
*storage = *i;
145
storage->
set_strtab
(NULL);
146
storage->
set_offset
(
SgAsmGenericString::unallocated
);
147
}
148
p_storage_list
.clear();
149
p_dont_free
= NULL;
/*FIXME: can't delete for same reason as in SgAsmStoredString destructor. (RPM 2008-09-05) */
150
}
151
155
SgAsmStringStorage
*
156
SgAsmElfStrtab::create_storage
(
rose_addr_t
offset
,
bool
shared)
157
{
158
ROSE_ASSERT(offset!=
SgAsmGenericString::unallocated
);
159
160
/* Has this string already been created? If so, return previous storage object. However, never share the empty_string at
161
* offset zero created when this string table was constructed because the ELF spec says it needs to stay there whether
162
* referenced or not. */
163
if
(shared) {
164
for
(referenced_t::iterator i=
p_storage_list
.begin(); i!=
p_storage_list
.end(); i++) {
165
if
((*i)->get_offset()==offset && (*i) !=
p_dont_free
)
166
return
*i;
167
}
168
}
169
170
/* Create a new storage object at this offset. */
171
SgAsmStringStorage
*storage = NULL;
172
if
(0==offset && 0==
get_container
()->
get_data
().
size
()) {
173
ROSE_ASSERT(
get_container
()->get_size()>=1);
174
storage =
new
SgAsmStringStorage
(
this
,
""
, 0);
175
}
else
{
176
std::string s =
get_container
()->
read_content_local_str
(offset);
177
storage =
new
SgAsmStringStorage
(
this
, s, offset);
178
}
179
180
/* It's a bad idea to free (e.g., modify) strings before we've identified all the strings in the table. Consider
181
* the case where offset 1 is "domain" and offset 3 is "main" (i.e., they overlap). If we modify "main" before knowing
182
* about "domain" then we'll end up freeing the last part of "domain" (and possibly replacing it with something else)!
183
*
184
* The only time we can guarantee this is OK is when the new storage points to the same file location as "dont_free"
185
* since the latter is guaranteed to never be freed or shared. This exception is used when creating a new, unallocated
186
* string (see SgAsmStoredString(SgAsmGenericStrtab,const std::string&)). */
187
if
(
p_num_freed
>0 && (!
p_dont_free
|| offset!=
p_dont_free
->
get_offset
())) {
188
fprintf(stderr,
189
"SgAsmElfStrtab::create_storage(%"
PRIu64
"): %zu other string%s (of %zu created) in [%d] \"%s\""
190
" %s been modified and/or reallocated!\n"
,
191
offset,
p_num_freed
, 1==
p_num_freed
?
""
:
"s"
,
p_storage_list
.size(),
192
get_container
()->
get_id
(),
get_container
()->
get_name
()->
get_string
(
true
).c_str(),
193
1==
p_num_freed
?
"has"
:
"have"
);
194
ROSE_ASSERT(0==
p_num_freed
);
195
}
196
197
p_storage_list
.push_back(storage);
198
set_isModified
(
true
);
199
return
storage;
200
}
201
203
void
204
SgAsmElfStrtab::rebind
(
SgAsmStringStorage
*storage,
rose_addr_t
offset
)
205
{
206
ROSE_ASSERT(
p_dont_free
&& storage!=
p_dont_free
&& storage->
get_offset
()==
p_dont_free
->
get_offset
());
207
std::string s =
get_container
()->
read_content_local_str
(offset);
208
storage->
set_offset
(offset);
209
storage->
set_string
(s);
210
}
211
214
rose_addr_t
215
SgAsmElfStrtab::get_storage_size
(
const
SgAsmStringStorage
*storage) {
216
return
storage->
get_string
().size() + 1;
217
}
218
225
void
226
SgAsmElfStrtab::allocate_overlap
(
SgAsmStringStorage
*storage)
227
{
228
ROSE_ASSERT(storage->
get_offset
()==
SgAsmGenericString::unallocated
);
229
size_t
need = storage->
get_string
().size();
230
for
(
size_t
i=0; i<
p_storage_list
.size(); i++) {
231
SgAsmStringStorage
*existing =
p_storage_list
[i];
232
if
(existing->
get_offset
()!=
SgAsmGenericString::unallocated
) {
233
size_t
have = existing->
get_string
().size();
234
if
(need<=have && 0==existing->get_string().compare(have-need, need, storage->
get_string
())) {
235
/* An existing string ends with the new string. */
236
storage->
set_offset
(existing->
get_offset
() + (have-need));
237
return
;
238
}
else
if
(need>have && existing->
get_offset
()>=need-have &&
239
0==storage->
get_string
().compare(need-have, have, existing->
get_string
())) {
240
/* New string ends with an existing string. Check for, and allocate, free space. */
241
rose_addr_t
offset
= existing->
get_offset
() - (need-have);
/* positive diffs checked above */
242
if
(
get_freelist
().
subtract_from
(
Extent
(offset, need-have)).
size
()==0) {
243
get_freelist
().
allocate_at
(
Extent
(offset, need-have));
244
storage->
set_offset
(offset);
245
return
;
246
}
247
}
248
}
249
}
250
}
251
253
void
254
SgAsmElfStrtab::unparse
(std::ostream &f)
const
255
{
256
SgAsmGenericSection
*container =
get_container
();
257
258
/* Write strings with NUL termination. Shared strings will be written more than once, but that's OK. */
259
for
(
size_t
i=0; i<
p_storage_list
.size(); i++) {
260
SgAsmStringStorage
*storage =
p_storage_list
[i];
261
ROSE_ASSERT(storage->
get_offset
()!=
SgAsmGenericString::unallocated
);
262
rose_addr_t
at = container->
write
(f, storage->
get_offset
(), storage->
get_string
());
263
container->
write
(f, at,
'\0'
);
264
}
265
266
/* Fill free areas with zero */
267
for
(
ExtentMap::const_iterator
i=
get_freelist
().begin(); i!=
get_freelist
().
end
(); ++i) {
268
container->
write
(f, i->first.first(), std::string(i->first.size(),
'\0'
));
269
}
270
}
rose-edg4x
src
frontend
BinaryFormats
ElfStringTable.C
Generated on Mon May 5 2014 17:29:22 for ROSE by
1.8.4