-/* Copyright (c) 2014-2015. 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 <cstddef>
#include <cstdint>
-#include <cstdarg>
-#include <dwarf.h>
-#include <elfutils/libdw.h>
-
-#include "mc_object_info.h"
-#include "mc_private.h"
-#include "mc/LocationList.hpp"
-#include "mc/AddressSpace.hpp"
-#include "mc/Frame.hpp"
-#include "mc/ObjectInformation.hpp"
-#include "mc/DwarfExpression.hpp"
-#include "mc_dwarf.hpp"
+#include "src/mc/AddressSpace.hpp"
+#include "src/mc/DwarfExpression.hpp"
+#include "src/mc/Frame.hpp"
+#include "src/mc/LocationList.hpp"
+#include "src/mc/ObjectInformation.hpp"
+#include "src/mc/mc_dwarf.hpp"
+#include "src/mc/mc_private.hpp"
using simgrid::mc::remote;
namespace simgrid {
namespace dwarf {
-evaluation_error::~evaluation_error() {}
-
-}
-}
-
-namespace simgrid {
-namespace dwarf {
-
void execute(
const Dwarf_Op* ops, std::size_t n,
const ExpressionContext& context, ExpressionStack& stack)
for (size_t i = 0; i != n; ++i) {
const Dwarf_Op *op = ops + i;
std::uint8_t atom = op->atom;
+ intptr_t first;
+ intptr_t second;
switch (atom) {
case DW_OP_breg29:
case DW_OP_breg30:
case DW_OP_breg31:{
+ // Push register + constant:
int register_id = simgrid::dwarf::dwarf_register_to_libunwind(
op->atom - DW_OP_breg0);
unw_word_t res;
- if (!context.cursor)
- throw evaluation_error("Missin stack context");
+ if (not context.cursor)
+ throw evaluation_error("Missing stack context");
unw_get_reg(context.cursor, register_id, &res);
stack.push(res + op->number);
break;
}
- // Push the CFA (Canonical Frame Addresse):
+ // Push the CFA (Canonical Frame Address):
case DW_OP_call_frame_cfa:
{
- // UNW_X86_64_CFA does not return the CFA DWARF expects
- // (it is a synonym for UNW_X86_64_RSP) so copy the cursor,
- // unwind it once in order to find the parent SP:
-
- if (!context.cursor)
+ /* See 6.4 of DWARF4 (http://dwarfstd.org/doc/DWARF4.pdf#page=140):
+ *
+ * > Typically, the CFA is defined to be the value of the stack
+ * > pointer at the call site in the previous frame (which may be
+ * > different from its value on entry to the current frame).
+ *
+ * We need to unwind the frame in order to get the SP of the parent
+ * frame.
+ *
+ * Warning: the CFA returned by libunwind (UNW_X86_64_RSP, etc.)
+ * is the SP of the *current* frame. */
+
+ if (not context.cursor)
throw evaluation_error("Missint cursor");
// Get frame:
// ***** Constants:
// Short constant literals:
- // DW_OP_lit15 pushed the 15 on the stack.
case DW_OP_lit0:
case DW_OP_lit1:
case DW_OP_lit2:
case DW_OP_lit29:
case DW_OP_lit30:
case DW_OP_lit31:
+ // Push a literal/constant on the stack:
stack.push(atom - DW_OP_lit0);
break;
// Address from the base address of this ELF object.
// Push the address on the stack (base_address + argument).
case DW_OP_addr: {
- if (!context.object_info)
+ if (not context.object_info)
throw evaluation_error("No base address");
Dwarf_Off addr = (Dwarf_Off) (std::uintptr_t)
context.object_info->base_address() + op->number;
stack.pop();
break;
- // Swap the two top-most value of the stack:
case DW_OP_swap:
- std::swap(stack.top(), stack.top(1));
+ stack.swap();
break;
// Duplicate the value under the top of the stack:
// (stack.top() += stack.before_top()).
case DW_OP_plus:
- stack.push(stack.pop() + stack.pop());
+ first = stack.pop();
+ second = stack.pop();
+ stack.push(first + second);
break;
case DW_OP_mul:
- stack.push(stack.pop() * stack.pop());
+ first = stack.pop();
+ second = stack.pop();
+ stack.push(first * second);
break;
case DW_OP_plus_uconst:
break;
case DW_OP_minus:
- stack.push(stack.pop() - stack.pop());
+ first = stack.pop();
+ second = stack.pop();
+ stack.push(second - first);
break;
case DW_OP_and:
- stack.push(stack.pop() & stack.pop());
+ first = stack.pop();
+ second = stack.pop();
+ stack.push(first & second);
break;
case DW_OP_or:
- stack.push(stack.pop() | stack.pop());
+ first = stack.pop();
+ second = stack.pop();
+ stack.push(first | second);
break;
case DW_OP_xor:
- stack.push(stack.pop() ^ stack.pop());
+ first = stack.pop();
+ second = stack.pop();
+ stack.push(first ^ second);
break;
case DW_OP_nop:
case DW_OP_deref:
// Computed address:
- if (!context.address_space)
+ if (not context.address_space)
throw evaluation_error("Missing address space");
context.address_space->read_bytes(
&stack.top(), sizeof(uintptr_t), remote(stack.top()),
}
}
-
-extern "C" {
-
-/** \brief Find the frame base of a given frame
- *
- * \param frame
- * \param unw_cursor
- */
-void *mc_find_frame_base(simgrid::mc::Frame* frame, simgrid::mc::ObjectInformation* object_info,
- unw_cursor_t * unw_cursor)
-{
- simgrid::dwarf::Location location = simgrid::dwarf::resolve(
- frame->frame_base, object_info,
- unw_cursor, NULL, NULL, -1);
- if (location.in_memory())
- return location.address();
- else if (location.in_register()) {
- // This is a special case.
- // The register if not the location of the frame base
- // (a frame base cannot be located in a register)
- // Instead, DWARF defines this to mean that the register
- // contains the address of the frame base.
- unw_word_t word;
- unw_get_reg(unw_cursor, location.register_id(), &word);
- return (void*) word;
- }
- else xbt_die("Unexpected location type");
-
-}
-
-void mc_dwarf_location_list_init(
- simgrid::dwarf::LocationList* list, simgrid::mc::ObjectInformation* info,
- Dwarf_Die * die, Dwarf_Attribute * attr)
-{
- list->clear();
-
- std::ptrdiff_t offset = 0;
- Dwarf_Addr base, start, end;
- Dwarf_Op *ops;
- std::size_t len;
-
- while (1) {
-
- offset = dwarf_getlocations(attr, offset, &base, &start, &end, &ops, &len);
- if (offset == 0)
- return;
- else if (offset == -1)
- xbt_die("Error while loading location list");
-
- simgrid::dwarf::LocationListEntry entry;
- entry.expression = simgrid::dwarf::DwarfExpression(ops, ops + len);
-
- void *base = info->base_address();
- // If start == 0, this is not a location list:
- entry.lowpc = start == 0 ? NULL : (char *) base + start;
- entry.highpc = start == 0 ? NULL : (char *) base + end;
-
- list->push_back(std::move(entry));
- }
-
-}
-
-}