3 #include "ns3/assert.h"
4 #include "ns3/fatal-error.h"
19 : m_directory (directory),
23 overriden.
from =
"libc.so.6";
24 overriden.
to =
"libc-ns3.so";
26 overriden.
from =
"libpthread.so.0";
27 overriden.
to =
"libpthread-ns3.so";
29 overriden.
from =
"librt.so.1";
30 overriden.
to =
"librt-ns3.so";
32 overriden.
from =
"libm.so.6";
33 overriden.
to =
"libm-ns3.so";
40 std::string::size_type tmp = filename.find_last_of (
"/");
41 if (tmp == std::string::npos)
45 return filename.substr (tmp + 1, filename.size () - (tmp + 1));
51 NS_LOG_FUNCTION (
this << source << destination);
52 int src = open (source.c_str (), O_RDONLY);
53 int dst = open (destination.c_str (), O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
55 ssize_t bytes_read = read (src, buffer, 1024);
56 while (bytes_read > 0)
58 ssize_t bytes_written = 0;
59 while (bytes_written != bytes_read)
61 ssize_t written = write (dst, buffer + bytes_written, bytes_read - bytes_written);
62 bytes_written += written;
64 bytes_read = read (src, buffer, 1024);
68 NS_LOG_DEBUG (
"copied " << source <<
" to " << destination);
74 bool prelinked =
false;
76 while (dyn->d_tag != DT_NULL)
78 if (dyn->d_tag == DT_STRTAB)
80 dt_strtab = dyn->d_un.d_val;
82 else if (dyn->d_tag == DT_GNU_PRELINKED)
90 dt_strtab -= baseAddress;
98 unsigned long end = ~0;
99 unsigned long base = end;
100 for (
long i = 0; i < phnum; i++, phdr++)
102 if (phdr->p_type == PT_LOAD)
104 unsigned long ph_base = phdr->p_vaddr & ~(phdr->p_align - 1);
113 NS_LOG_ERROR (
"Could not find base address.");
127 else if (c < (10 + 25))
129 return c - 10 + 0x41;
131 else if (c < (10 + 25 + 25))
133 return c - (10 + 25) + 0x61;
141 if (uid >= 60 * 60 * 60 * 60)
143 NS_FATAL_ERROR (
"Please, report a bug: not enough unique strings for loaded code.");
145 uint8_t a = uid % 60;
146 uint8_t b = (uid / 60) % 60;
147 uint8_t c = (uid / 3600) % 60;
148 uint8_t d = (uid / 216000) % 60;
153 NS_LOG_DEBUG (
"wrote " << str);
157 ElfCache::EditBuffer (uint8_t *map, uint32_t selfId) const
159 ElfW (Ehdr) *header = (
ElfW (Ehdr) *)map;
160 ElfW (Phdr) * phdr = (
ElfW (Phdr) *)(map + header->e_phoff);
161 ElfW (Dyn) * dyn = 0;
166 ElfW (Phdr) * pt_load_rw = 0;
167 ElfW (Phdr) * pt_gnu_relro = 0;
168 for (uint32_t i = 0; i < header->e_phnum; i++, phdr++)
170 switch (phdr->p_type)
173 if (phdr->p_flags & PF_W)
181 dyn = (
ElfW (Dyn) *)(map + phdr->p_offset);
188 NS_ASSERT (pt_load_rw != 0);
189 fileInfo.
p_vaddr = pt_load_rw->p_vaddr;
190 fileInfo.
p_memsz = pt_load_rw->p_memsz;
191 if (pt_gnu_relro != 0)
193 NS_ASSERT (pt_gnu_relro->p_vaddr == pt_load_rw->p_vaddr);
194 fileInfo.
p_vaddr += pt_gnu_relro->p_memsz;
195 fileInfo.
p_memsz -= pt_gnu_relro->p_memsz;
202 ElfW (Dyn) * cur = dyn;
203 while (cur->d_tag != DT_NULL)
205 if (cur->d_tag == DT_NEEDED)
207 char *needed = (
char *)(map + dt_strtab + cur->d_un.d_val);
208 if (std::string (needed) !=
"ld-linux-x86-64.so.2"
209 && std::string (needed) !=
"ld-linux.so.2")
212 fileInfo.
deps.push_back (
id);
216 else if (cur->d_tag == DT_SONAME)
218 char *soname = (
char *)(map + dt_strtab + cur->d_un.d_val);
221 else if (cur->d_tag == DT_INIT)
223 dt_init = cur->d_un.d_val;
229 while (cur->d_tag != DT_NULL)
231 if (cur->d_tag == DT_FINI)
233 cur->d_tag = DT_INIT;
234 cur->d_un.d_val = dt_init;
236 else if (cur->d_tag == DT_FINI_ARRAYSZ)
246 ElfCache::EditFile (std::string filename, uint32_t selfId) const
248 NS_LOG_FUNCTION (
this << filename);
249 int fd = ::open (filename.c_str (), O_RDWR);
250 NS_ASSERT_MSG (fd != -1,
"unable to open file=" << filename <<
" error=" << strerror (
errno));
252 int retval = ::fstat (fd, &st);
253 NS_ASSERT_MSG (retval == 0,
"unable to fstat file=" << filename <<
" error=" << strerror (
errno));
254 uint64_t size = st.st_size;
255 uint8_t *buffer = (uint8_t *) ::mmap (0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
256 NS_ASSERT_MSG (buffer != MAP_FAILED,
"unable to mmap file=" << filename <<
" error=" << strerror (
errno));
262 retval = ::msync (buffer, size, MS_SYNC);
263 NS_ASSERT_MSG (retval == 0,
"msync failed " << strerror (
errno));
265 retval = ::munmap (buffer, size);
266 NS_ASSERT_MSG (retval == 0,
"munmap failed " << strerror (
errno));
274 static uint32_t
id = 0;
282 for (std::vector<struct Overriden>::const_iterator i =
m_overriden.begin (); i !=
m_overriden.end (); ++i)
285 if (overriden.
from == depname)
287 depname = overriden.
to;
289 NS_LOG_DEBUG (
"from: " << overriden.
from <<
", to: " << overriden.
to);
291 for (std::vector<struct ElfCachedFile>::const_iterator i =
m_files.begin (); i !=
m_files.end (); ++i)
293 NS_LOG_DEBUG (
"cache: " << i->basename);
294 if (depname == i->basename)
299 NS_ASSERT_MSG (
false,
"did not find " << depname);
306 int retval = ::mkdir (
m_directory.c_str (), S_IRWXU);
309 NS_LOG_DEBUG (
"Created elf loader cache directory.");
311 std::ostringstream oss;
313 retval = ::mkdir (oss.str ().c_str (), S_IRWXU);
316 NS_LOG_DEBUG (
"Created elf loader cache directory.");
324 NS_LOG_FUNCTION (
this << filename);
327 for (std::vector<struct Overriden>::const_iterator i =
m_overriden.begin (); i !=
m_overriden.end (); ++i)
333 for (std::vector<struct ElfCachedFile>::const_iterator i =
m_files.begin (); i !=
m_files.end (); ++i)
335 if (i->basename == overriden.
to)
345 for (std::vector<struct ElfCachedFile>::const_iterator i =
m_files.begin (); i !=
m_files.end (); ++i)
354 std::string fileCopy = directory +
"/" +
basename;