-/* Copyright (c) 2014-2019. The SimGrid Team.
- * All rights reserved. */
+/* Copyright (c) 2014-2019. The SimGrid Team. All rights reserved. */
/* This program is free software; you can redistribute it and/or modify it
* under the terms of the license (GNU LGPL) which comes with this package. */
#include <cstdint>
-
+#include <sys/mman.h> // PROT_READ and friends
#include <vector>
#include "src/mc/inspect/Frame.hpp"
#include "src/mc/inspect/ObjectInformation.hpp"
#include "src/mc/inspect/Variable.hpp"
+#include "src/mc/mc_private.hpp"
+#include "xbt/file.hpp"
namespace simgrid {
namespace mc {
* (there is no offset) i.e.
* \f$\text{virtual address} = \{dwarf address}\f$
*
- * For a shared object, the addreses are offset from the begining
+ * For a shared object, the addresses are offset from the begining
* of the shared object (the base address of the mapped shared
* object must be used as offset
* i.e. \f$\text{virtual address} = \text{shared object base address}
if (this->executable())
return nullptr;
- // For an a shared-object (ET_DYN, including position-independant executables)
+ // For an a shared-object (ET_DYN, including position-independent executables)
// the base address is its lowest address:
void* result = this->start_exec;
if (this->start_rw != nullptr && result > (void*)this->start_rw)
simgrid::mc::remove_local_variable(entry.second, var_name, subprogram_name, entry.second);
}
+/** @brief Fills the position of the segments (executable, read-only, read/write) */
+// TODO, use the ELF segment information for more robustness
+void find_object_address(std::vector<simgrid::xbt::VmMap> const& maps, simgrid::mc::ObjectInformation* result)
+{
+ const int PROT_RW = PROT_READ | PROT_WRITE;
+ const int PROT_RX = PROT_READ | PROT_EXEC;
+
+ std::string name = simgrid::xbt::Path(result->file_name).get_base_name();
+
+ for (size_t i = 0; i < maps.size(); ++i) {
+ simgrid::xbt::VmMap const& reg = maps[i];
+ if (maps[i].pathname.empty())
+ continue;
+ std::string map_basename = simgrid::xbt::Path(maps[i].pathname).get_base_name();
+ if (map_basename != name)
+ continue;
+
+ // This is the non-GNU_RELRO-part of the data segment:
+ if (reg.prot == PROT_RW) {
+ xbt_assert(not result->start_rw, "Multiple read-write segments for %s, not supported", maps[i].pathname.c_str());
+ result->start_rw = (char*)reg.start_addr;
+ result->end_rw = (char*)reg.end_addr;
+
+ // The next VMA might be end of the data segment:
+ if (i + 1 < maps.size() && maps[i + 1].pathname.empty() && maps[i + 1].prot == PROT_RW &&
+ maps[i + 1].start_addr == reg.end_addr)
+ result->end_rw = (char*)maps[i + 1].end_addr;
+ }
+
+ // This is the text segment:
+ else if (reg.prot == PROT_RX) {
+ xbt_assert(not result->start_exec, "Multiple executable segments for %s, not supported",
+ maps[i].pathname.c_str());
+ result->start_exec = (char*)reg.start_addr;
+ result->end_exec = (char*)reg.end_addr;
+
+ // The next VMA might be end of the data segment:
+ if (i + 1 < maps.size() && maps[i + 1].pathname.empty() && maps[i + 1].prot == PROT_RW &&
+ maps[i + 1].start_addr == reg.end_addr) {
+ result->start_rw = (char*)maps[i + 1].start_addr;
+ result->end_rw = (char*)maps[i + 1].end_addr;
+ }
+ }
+
+ // This is the GNU_RELRO-part of the data segment:
+ else if (reg.prot == PROT_READ) {
+ xbt_assert(not result->start_ro, "Multiple read only segments for %s, not supported", maps[i].pathname.c_str());
+ result->start_ro = (char*)reg.start_addr;
+ result->end_ro = (char*)reg.end_addr;
+ }
+ }
+
+ result->start = result->start_rw;
+ if ((const void*)result->start_ro < result->start)
+ result->start = result->start_ro;
+ if ((const void*)result->start_exec < result->start)
+ result->start = result->start_exec;
+
+ result->end = result->end_rw;
+ if (result->end_ro && (const void*)result->end_ro > result->end)
+ result->end = result->end_ro;
+ if (result->end_exec && (const void*)result->end_exec > result->end)
+ result->end = result->end_exec;
+
+ xbt_assert(result->start_exec || result->start_rw || result->start_ro);
+}
+
} // namespace mc
} // namespace simgrid