1b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Copyright 2010 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/gdb-jit.h"
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include <memory>
8f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/platform/platform.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/bootstrapper.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/frames-inl.h"
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/frames.h"
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/global-handles.h"
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/messages.h"
16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/objects.h"
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ostreams.h"
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/snapshot/natives.h"
19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/splay-tree-inl.h"
20b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
21b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochnamespace v8 {
22b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochnamespace internal {
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochnamespace GDBJITInterface {
24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifdef ENABLE_GDB_JIT_INTERFACE
26b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#ifdef __APPLE__
283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __MACH_O
293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass MachO;
303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass MachOSection;
313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtypedef MachO DebugObject;
323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtypedef MachOSection DebugSection;
333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#else
343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ELF
35b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochclass ELF;
363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass ELFSection;
373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtypedef ELF DebugObject;
383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtypedef ELFSection DebugSection;
393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
40b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
41b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochclass Writer BASE_EMBEDDED {
42b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  explicit Writer(DebugObject* debug_object)
443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      : debug_object_(debug_object),
45b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        position_(0),
46b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        capacity_(1024),
47b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        buffer_(reinterpret_cast<byte*>(malloc(capacity_))) {
48b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
49b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
50b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ~Writer() {
51b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    free(buffer_);
52b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
53b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
54b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uintptr_t position() const {
55b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return position_;
56b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
57b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
58b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  template<typename T>
59b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  class Slot {
60b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch   public:
61b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Slot(Writer* w, uintptr_t offset) : w_(w), offset_(offset) { }
62b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
63b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    T* operator-> () {
64b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      return w_->RawSlotAt<T>(offset_);
65b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
66b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
67b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    void set(const T& value) {
68b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      *w_->RawSlotAt<T>(offset_) = value;
69b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
70b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
71b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Slot<T> at(int i) {
72b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      return Slot<T>(w_, offset_ + sizeof(T) * i);
73b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
74b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
75b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch   private:
76b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Writer* w_;
77b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uintptr_t offset_;
78b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
79b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
80b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  template<typename T>
81b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void Write(const T& val) {
82b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Ensure(position_ + sizeof(T));
83b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    *RawSlotAt<T>(position_) = val;
84b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    position_ += sizeof(T);
85b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
86b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
87b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  template<typename T>
88b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Slot<T> SlotAt(uintptr_t offset) {
89b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Ensure(offset + sizeof(T));
90b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return Slot<T>(this, offset);
91b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
92b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
93b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  template<typename T>
94b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Slot<T> CreateSlotHere() {
95b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return CreateSlotsHere<T>(1);
96b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
97b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
98b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  template<typename T>
99b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Slot<T> CreateSlotsHere(uint32_t count) {
100b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uintptr_t slot_position = position_;
101b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    position_ += sizeof(T) * count;
102b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Ensure(position_);
103b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return SlotAt<T>(slot_position);
104b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
105b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
106b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void Ensure(uintptr_t pos) {
107b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    if (capacity_ < pos) {
108b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      while (capacity_ < pos) capacity_ *= 2;
109b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      buffer_ = reinterpret_cast<byte*>(realloc(buffer_, capacity_));
110b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
111b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
112b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  DebugObject* debug_object() { return debug_object_; }
114b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
115b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  byte* buffer() { return buffer_; }
116b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
117b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void Align(uintptr_t align) {
118b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uintptr_t delta = position_ % align;
119b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    if (delta == 0) return;
120b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uintptr_t padding = align - delta;
121b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Ensure(position_ += padding);
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK((position_ % align) == 0);
123b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
124b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
125b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void WriteULEB128(uintptr_t value) {
126b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    do {
127b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      uint8_t byte = value & 0x7F;
128b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      value >>= 7;
129b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      if (value != 0) byte |= 0x80;
130b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      Write<uint8_t>(byte);
131b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    } while (value != 0);
132b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
133b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
134b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void WriteSLEB128(intptr_t value) {
135b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    bool more = true;
136b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    while (more) {
137b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      int8_t byte = value & 0x7F;
138b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      bool byte_sign = byte & 0x40;
139b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      value >>= 7;
140b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
141b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      if ((value == 0 && !byte_sign) || (value == -1 && byte_sign)) {
142b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        more = false;
143b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      } else {
144b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        byte |= 0x80;
145b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      }
146b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
147b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      Write<int8_t>(byte);
148b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
149b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
150b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
151b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void WriteString(const char* str) {
152b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    do {
153b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      Write<char>(*str);
154b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    } while (*str++);
155b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
156b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
157b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
158b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  template<typename T> friend class Slot;
159b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
160b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  template<typename T>
161b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  T* RawSlotAt(uintptr_t offset) {
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(offset < capacity_ && offset + sizeof(T) <= capacity_);
163b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return reinterpret_cast<T*>(&buffer_[offset]);
164b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
165b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  DebugObject* debug_object_;
167b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uintptr_t position_;
168b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uintptr_t capacity_;
169b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  byte* buffer_;
170b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
171b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ELFStringTable;
173b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtemplate<typename THeader>
1753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass DebugSectionBase : public ZoneObject {
176b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
1773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual ~DebugSectionBase() { }
1783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual void WriteBody(Writer::Slot<THeader> header, Writer* writer) {
1803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uintptr_t start = writer->position();
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (WriteBodyInternal(writer)) {
1823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      uintptr_t end = writer->position();
183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      header->offset = static_cast<uint32_t>(start);
1843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#if defined(__MACH_O)
1853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      header->addr = 0;
1863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
1873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      header->size = end - start;
1883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
1893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual bool WriteBodyInternal(Writer* writer) {
1923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return false;
1933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  typedef THeader Header;
1963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch};
1973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstruct MachOSectionHeader {
2003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  char sectname[16];
2013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  char segname[16];
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
2033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t addr;
2043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t size;
2053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#else
2063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint64_t addr;
2073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint64_t size;
2083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
2093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t offset;
2103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t align;
2113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t reloff;
2123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t nreloc;
2133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t flags;
2143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t reserved1;
2153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t reserved2;
2163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch};
2173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass MachOSection : public DebugSectionBase<MachOSectionHeader> {
2203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public:
2213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  enum Type {
2223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    S_REGULAR = 0x0u,
2233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    S_ATTR_COALESCED = 0xbu,
2243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    S_ATTR_SOME_INSTRUCTIONS = 0x400u,
2253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    S_ATTR_DEBUG = 0x02000000u,
2263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    S_ATTR_PURE_INSTRUCTIONS = 0x80000000u
227b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
228b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MachOSection(const char* name, const char* segment, uint32_t align,
2303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch               uint32_t flags)
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : name_(name), segment_(segment), align_(align), flags_(flags) {
2323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (align_ != 0) {
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(base::bits::IsPowerOfTwo32(align));
2343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      align_ = WhichPowerOf2(align_);
2353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
2373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual ~MachOSection() { }
2393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual void PopulateHeader(Writer::Slot<Header> header) {
2413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->addr = 0;
2423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->size = 0;
2433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->offset = 0;
2443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->align = align_;
2453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->reloff = 0;
2463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->nreloc = 0;
2473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->flags = flags_;
2483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->reserved1 = 0;
2493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->reserved2 = 0;
2503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    memset(header->sectname, 0, sizeof(header->sectname));
2513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    memset(header->segname, 0, sizeof(header->segname));
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(strlen(name_) < sizeof(header->sectname));
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(strlen(segment_) < sizeof(header->segname));
2543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    strncpy(header->sectname, name_, sizeof(header->sectname));
2553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    strncpy(header->segname, segment_, sizeof(header->segname));
2563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
2573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private:
2593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const char* name_;
2603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const char* segment_;
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint32_t align_;
2623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t flags_;
2633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch};
2643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstruct ELFSectionHeader {
2673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t name;
2683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t type;
2693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uintptr_t flags;
2703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uintptr_t address;
2713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uintptr_t offset;
2723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uintptr_t size;
2733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t link;
2743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t info;
2753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uintptr_t alignment;
2763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uintptr_t entry_size;
2773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch};
2783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#if defined(__ELF)
2813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass ELFSection : public DebugSectionBase<ELFSectionHeader> {
2823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public:
283b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  enum Type {
284b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_NULL = 0,
285b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_PROGBITS = 1,
286b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_SYMTAB = 2,
287b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_STRTAB = 3,
288b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_RELA = 4,
289b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_HASH = 5,
290b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_DYNAMIC = 6,
291b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_NOTE = 7,
292b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_NOBITS = 8,
293b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_REL = 9,
294b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_SHLIB = 10,
295b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_DYNSYM = 11,
296b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_LOPROC = 0x70000000,
2971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    TYPE_X86_64_UNWIND = 0x70000001,
298b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_HIPROC = 0x7fffffff,
299b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_LOUSER = 0x80000000,
300b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_HIUSER = 0xffffffff
301b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
302b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
303b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  enum Flags {
304b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    FLAG_WRITE = 1,
305b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    FLAG_ALLOC = 2,
306b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    FLAG_EXEC = 4
307b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
308b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
309b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  enum SpecialIndexes {
310b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    INDEX_ABSOLUTE = 0xfff1
311b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
312b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
313b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ELFSection(const char* name, Type type, uintptr_t align)
314b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      : name_(name), type_(type), align_(align) { }
315b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
316b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  virtual ~ELFSection() { }
317b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void PopulateHeader(Writer::Slot<Header> header, ELFStringTable* strtab);
319b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
320b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
321b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uintptr_t start = w->position();
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (WriteBodyInternal(w)) {
323b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      uintptr_t end = w->position();
324b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      header->offset = start;
325b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      header->size = end - start;
326b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
327b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
328b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual bool WriteBodyInternal(Writer* w) {
330b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return false;
331b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
332b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
333b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uint16_t index() const { return index_; }
334b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void set_index(uint16_t index) { index_ = index; }
335b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
336b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch protected:
337b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  virtual void PopulateHeader(Writer::Slot<Header> header) {
338b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->flags = 0;
339b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->address = 0;
340b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->offset = 0;
341b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->size = 0;
342b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->link = 0;
343b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->info = 0;
344b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->entry_size = 0;
345b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
346b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
347b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
348b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  const char* name_;
349b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Type type_;
350b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uintptr_t align_;
351b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uint16_t index_;
352b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
3533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif  // defined(__ELF)
354b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
355b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
3563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#if defined(__MACH_O)
3573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass MachOTextSection : public MachOSection {
3583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public:
359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MachOTextSection(uint32_t align, uintptr_t addr, uintptr_t size)
360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : MachOSection("__text", "__TEXT", align,
3613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                     MachOSection::S_REGULAR |
3623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         MachOSection::S_ATTR_SOME_INSTRUCTIONS |
3633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         MachOSection::S_ATTR_PURE_INSTRUCTIONS),
3643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        addr_(addr),
365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        size_(size) {}
3663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch protected:
3683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual void PopulateHeader(Writer::Slot<Header> header) {
3693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    MachOSection::PopulateHeader(header);
3703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->addr = addr_;
3713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->size = size_;
3723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private:
3753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uintptr_t addr_;
3763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uintptr_t size_;
3773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch};
3783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif  // defined(__MACH_O)
3793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#if defined(__ELF)
382b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochclass FullHeaderELFSection : public ELFSection {
383b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
384b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  FullHeaderELFSection(const char* name,
385b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                       Type type,
386b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                       uintptr_t align,
387b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                       uintptr_t addr,
388b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                       uintptr_t offset,
389b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                       uintptr_t size,
390b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                       uintptr_t flags)
391b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      : ELFSection(name, type, align),
392b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        addr_(addr),
393b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        offset_(offset),
394b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        size_(size),
395b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        flags_(flags) { }
396b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
397b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch protected:
398b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  virtual void PopulateHeader(Writer::Slot<Header> header) {
399b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    ELFSection::PopulateHeader(header);
400b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->address = addr_;
401b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->offset = offset_;
402b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->size = size_;
403b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->flags = flags_;
404b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
405b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
406b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
407b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uintptr_t addr_;
408b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uintptr_t offset_;
409b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uintptr_t size_;
410b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uintptr_t flags_;
411b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
412b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
413b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ELFStringTable : public ELFSection {
415b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit ELFStringTable(const char* name)
417b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      : ELFSection(name, TYPE_STRTAB, 1), writer_(NULL), offset_(0), size_(0) {
418b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
419b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
420b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uintptr_t Add(const char* str) {
421b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    if (*str == '\0') return 0;
422b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
423b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uintptr_t offset = size_;
424b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    WriteString(str);
425b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return offset;
426b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
427b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
428b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void AttachWriter(Writer* w) {
429b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    writer_ = w;
430b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    offset_ = writer_->position();
431b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
432b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    // First entry in the string table should be an empty string.
433b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    WriteString("");
434b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
435b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
436b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void DetachWriter() {
437b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    writer_ = NULL;
438b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
439b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
440b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(writer_ == NULL);
442b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->offset = offset_;
443b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->size = size_;
444b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
445b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
446b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
447b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void WriteString(const char* str) {
448b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uintptr_t written = 0;
449b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    do {
450b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      writer_->Write(*str);
451b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      written++;
452b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    } while (*str++);
453b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    size_ += written;
454b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
455b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
456b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Writer* writer_;
457b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
458b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uintptr_t offset_;
459b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uintptr_t size_;
460b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
461b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
462b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
463b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header,
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                ELFStringTable* strtab) {
465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  header->name = static_cast<uint32_t>(strtab->Add(name_));
466b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  header->type = type_;
467b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  header->alignment = align_;
468b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  PopulateHeader(header);
469b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
4703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif  // defined(__ELF)
4713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#if defined(__MACH_O)
4743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass MachO BASE_EMBEDDED {
4753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public:
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit MachO(Zone* zone) : zone_(zone), sections_(6, zone) { }
4773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  uint32_t AddSection(MachOSection* section) {
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sections_.Add(section, zone_);
4803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return sections_.length() - 1;
4813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
4823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Write(Writer* w, uintptr_t code_start, uintptr_t code_size) {
4843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Writer::Slot<MachOHeader> header = WriteHeader(w);
4853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uintptr_t load_command_start = w->position();
4863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Writer::Slot<MachOSegmentCommand> cmd = WriteSegmentCommand(w,
4873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                                code_start,
4883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                                code_size);
4893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    WriteSections(w, cmd, header, load_command_start);
4903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
4913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
4923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private:
4933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  struct MachOHeader {
4943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t magic;
4953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t cputype;
4963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t cpusubtype;
4973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t filetype;
4983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t ncmds;
4993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t sizeofcmds;
5003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t flags;
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_X64
5023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t reserved;
5033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
5043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  };
5053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  struct MachOSegmentCommand {
5073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t cmd;
5083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t cmdsize;
5093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    char segname[16];
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
5113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t vmaddr;
5123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t vmsize;
5133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t fileoff;
5143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t filesize;
5153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#else
5163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint64_t vmaddr;
5173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint64_t vmsize;
5183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint64_t fileoff;
5193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint64_t filesize;
5203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
5213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t maxprot;
5223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t initprot;
5233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t nsects;
5243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t flags;
5253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  };
5263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  enum MachOLoadCommandCmd {
5283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    LC_SEGMENT_32 = 0x00000001u,
5293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    LC_SEGMENT_64 = 0x00000019u
5303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  };
5313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Writer::Slot<MachOHeader> WriteHeader(Writer* w) {
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(w->position() == 0);
5353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Writer::Slot<MachOHeader> header = w->CreateSlotHere<MachOHeader>();
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
5373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->magic = 0xFEEDFACEu;
5383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->cputype = 7;  // i386
5393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->cpusubtype = 3;  // CPU_SUBTYPE_I386_ALL
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#elif V8_TARGET_ARCH_X64
5413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->magic = 0xFEEDFACFu;
5423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->cputype = 7 | 0x01000000;  // i386 | 64-bit ABI
5433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->cpusubtype = 3;  // CPU_SUBTYPE_I386_ALL
5443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->reserved = 0;
5453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#else
5463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#error Unsupported target architecture.
5473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
5483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->filetype = 0x1;  // MH_OBJECT
5493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->ncmds = 1;
5503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->sizeofcmds = 0;
5513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    header->flags = 0;
5523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return header;
5533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
554b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
555b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
5563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Writer::Slot<MachOSegmentCommand> WriteSegmentCommand(Writer* w,
5573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                        uintptr_t code_start,
5583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                        uintptr_t code_size) {
5593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Writer::Slot<MachOSegmentCommand> cmd =
5603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->CreateSlotHere<MachOSegmentCommand>();
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
5623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmd->cmd = LC_SEGMENT_32;
5633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#else
5643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmd->cmd = LC_SEGMENT_64;
5653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
5663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmd->vmaddr = code_start;
5673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmd->vmsize = code_size;
5683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmd->fileoff = 0;
5693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmd->filesize = 0;
5703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmd->maxprot = 7;
5713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmd->initprot = 7;
5723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmd->flags = 0;
5733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmd->nsects = sections_.length();
5743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    memset(cmd->segname, 0, 16);
5753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmd->cmdsize = sizeof(MachOSegmentCommand) + sizeof(MachOSection::Header) *
5763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        cmd->nsects;
5773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return cmd;
5783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void WriteSections(Writer* w,
5823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                     Writer::Slot<MachOSegmentCommand> cmd,
5833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                     Writer::Slot<MachOHeader> header,
5843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                     uintptr_t load_command_start) {
5853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Writer::Slot<MachOSection::Header> headers =
5863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->CreateSlotsHere<MachOSection::Header>(sections_.length());
5873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmd->fileoff = w->position();
588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    header->sizeofcmds =
589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        static_cast<uint32_t>(w->position() - load_command_start);
5903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    for (int section = 0; section < sections_.length(); ++section) {
5913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      sections_[section]->PopulateHeader(headers.at(section));
5923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      sections_[section]->WriteBody(headers.at(section), w);
5933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
5943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    cmd->filesize = w->position() - (uintptr_t)cmd->fileoff;
5953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
5963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Zone* zone_;
5983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ZoneList<MachOSection*> sections_;
5993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch};
6003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif  // defined(__MACH_O)
6013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#if defined(__ELF)
604b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochclass ELF BASE_EMBEDDED {
605b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit ELF(Zone* zone) : zone_(zone), sections_(6, zone) {
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sections_.Add(new(zone) ELFSection("", ELFSection::TYPE_NULL, 0), zone);
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sections_.Add(new(zone) ELFStringTable(".shstrtab"), zone);
609b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
610b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
611b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void Write(Writer* w) {
612b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    WriteHeader(w);
613b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    WriteSectionTable(w);
614b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    WriteSections(w);
615b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
616b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
617b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ELFSection* SectionAt(uint32_t index) {
618b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return sections_[index];
619b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
620b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
621b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uint32_t AddSection(ELFSection* section) {
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sections_.Add(section, zone_);
623b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    section->set_index(sections_.length() - 1);
624b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return sections_.length() - 1;
625b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
626b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
627b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
628b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  struct ELFHeader {
629b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint8_t ident[16];
630b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint16_t type;
631b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint16_t machine;
632b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint32_t version;
633b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uintptr_t entry;
634b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uintptr_t pht_offset;
635b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uintptr_t sht_offset;
636b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint32_t flags;
637b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint16_t header_size;
638b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint16_t pht_entry_size;
639b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint16_t pht_entry_num;
640b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint16_t sht_entry_size;
641b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint16_t sht_entry_num;
642b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint16_t sht_strtab_index;
643b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
644b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
645b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
646b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void WriteHeader(Writer* w) {
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(w->position() == 0);
648b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Writer::Slot<ELFHeader> header = w->CreateSlotHere<ELFHeader>();
649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_X87 || \
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch     (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT))
651b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    const uint8_t ident[16] =
652b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        { 0x7f, 'E', 'L', 'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#elif(V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT) || \
654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    (V8_TARGET_ARCH_PPC64 && V8_TARGET_LITTLE_ENDIAN)
655b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    const uint8_t ident[16] =
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        { 0x7f, 'E', 'L', 'F', 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#elif V8_TARGET_ARCH_PPC64 && V8_TARGET_BIG_ENDIAN && V8_OS_LINUX
658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const uint8_t ident[16] = {0x7f, 'E', 'L', 'F', 2, 2, 1, 0,
659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                               0,    0,   0,   0,   0, 0, 0, 0};
6603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#elif V8_TARGET_ARCH_S390X
6613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    const uint8_t ident[16] = {0x7f, 'E', 'L', 'F', 2, 2, 1, 3,
6623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                               0,    0,   0,   0,   0, 0, 0, 0};
6633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#elif V8_TARGET_ARCH_S390
6643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    const uint8_t ident[16] = {0x7f, 'E', 'L', 'F', 1, 2, 1, 3,
6653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                               0,    0,   0,   0,   0, 0, 0, 0};
666b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#else
667b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#error Unsupported target architecture.
668b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif
669b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    memcpy(header->ident, ident, 16);
670b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->type = 1;
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
672b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->machine = 3;
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#elif V8_TARGET_ARCH_X64
674b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    // Processor identification value for x64 is 62 as defined in
675b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    //    System V ABI, AMD64 Supplement
676b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    //    http://www.x86-64.org/documentation/abi.pdf
677b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->machine = 62;
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#elif V8_TARGET_ARCH_ARM
679e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Set to EM_ARM, defined as 40, in "ARM ELF File Format" at
680e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // infocenter.arm.com/help/topic/com.arm.doc.dui0101a/DUI0101A_Elf.pdf
681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    header->machine = 40;
682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#elif V8_TARGET_ARCH_PPC64 && V8_OS_LINUX
683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Set to EM_PPC64, defined as 21, in Power ABI,
684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Join the next 4 lines, omitting the spaces and double-slashes.
685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // https://www-03.ibm.com/technologyconnect/tgcm/TGCMFileServlet.wss/
686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // ABI64BitOpenPOWERv1.1_16July2015_pub.pdf?
687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // id=B81AEC1A37F5DAF185257C3E004E8845&linkid=1n0000&c_t=
688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // c9xw7v5dzsj7gt1ifgf4cjbcnskqptmr
689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    header->machine = 21;
6903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#elif V8_TARGET_ARCH_S390
6913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // Processor identification value is 22 (EM_S390) as defined in the ABI:
6923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_s390.html#AEN1691
6933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    // http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_zSeries.html#AEN1599
6943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    header->machine = 22;
695b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#else
696b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#error Unsupported target architecture.
697b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif
698b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->version = 1;
699b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->entry = 0;
700b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->pht_offset = 0;
701b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->sht_offset = sizeof(ELFHeader);  // Section table follows header.
702b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->flags = 0;
703b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->header_size = sizeof(ELFHeader);
704b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->pht_entry_size = 0;
705b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->pht_entry_num = 0;
706b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->sht_entry_size = sizeof(ELFSection::Header);
707b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->sht_entry_num = sections_.length();
708b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->sht_strtab_index = 1;
709b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
710b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
711b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void WriteSectionTable(Writer* w) {
712b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    // Section headers table immediately follows file header.
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(w->position() == sizeof(ELFHeader));
714b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
715b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Writer::Slot<ELFSection::Header> headers =
716b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        w->CreateSlotsHere<ELFSection::Header>(sections_.length());
717b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
718b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    // String table for section table is the first section.
719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ELFStringTable* strtab = static_cast<ELFStringTable*>(SectionAt(1));
720b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    strtab->AttachWriter(w);
721b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    for (int i = 0, length = sections_.length();
722b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         i < length;
723b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         i++) {
724b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      sections_[i]->PopulateHeader(headers.at(i), strtab);
725b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
726b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    strtab->DetachWriter();
727b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
728b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
729b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int SectionHeaderPosition(uint32_t section_index) {
730b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return sizeof(ELFHeader) + sizeof(ELFSection::Header) * section_index;
731b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
732b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
733b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void WriteSections(Writer* w) {
734b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Writer::Slot<ELFSection::Header> headers =
735b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        w->SlotAt<ELFSection::Header>(sizeof(ELFHeader));
736b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
737b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    for (int i = 0, length = sections_.length();
738b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         i < length;
739b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         i++) {
740b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      sections_[i]->WriteBody(headers.at(i), w);
741b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
742b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
743b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Zone* zone_;
745b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ZoneList<ELFSection*> sections_;
746b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
747b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
748b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
749b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochclass ELFSymbol BASE_EMBEDDED {
750b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
751b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  enum Type {
752b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_NOTYPE = 0,
753b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_OBJECT = 1,
754b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_FUNC = 2,
755b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_SECTION = 3,
756b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_FILE = 4,
757b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_LOPROC = 13,
758b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    TYPE_HIPROC = 15
759b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
760b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
761b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  enum Binding {
762b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    BIND_LOCAL = 0,
763b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    BIND_GLOBAL = 1,
764b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    BIND_WEAK = 2,
765b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    BIND_LOPROC = 13,
766b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    BIND_HIPROC = 15
767b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
768b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
769b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ELFSymbol(const char* name,
770b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            uintptr_t value,
771b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            uintptr_t size,
772b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            Binding binding,
773b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            Type type,
774b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch            uint16_t section)
775b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      : name(name),
776b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        value(value),
777b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        size(size),
778b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        info((binding << 4) | type),
779b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        other(0),
780b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        section(section) {
781b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
782b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
783b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Binding binding() const {
784b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return static_cast<Binding>(info >> 4);
785b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_X87 || \
7873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch     (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT) ||                   \
7883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch     (V8_TARGET_ARCH_S390 && V8_TARGET_ARCH_32_BIT))
789b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  struct SerializedLayout {
790b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    SerializedLayout(uint32_t name,
791b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                     uintptr_t value,
792b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                     uintptr_t size,
793b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                     Binding binding,
794b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                     Type type,
795b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                     uint16_t section)
796b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        : name(name),
797b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          value(value),
798b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          size(size),
799b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          info((binding << 4) | type),
800b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          other(0),
801b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          section(section) {
802b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
803b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
804b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint32_t name;
805b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uintptr_t value;
806b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uintptr_t size;
807b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint8_t info;
808b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint8_t other;
809b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint16_t section;
810b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
811014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#elif(V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT) || \
8123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    (V8_TARGET_ARCH_PPC64 && V8_OS_LINUX) || V8_TARGET_ARCH_S390X
813b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  struct SerializedLayout {
814b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    SerializedLayout(uint32_t name,
815b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                     uintptr_t value,
816b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                     uintptr_t size,
817b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                     Binding binding,
818b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                     Type type,
819b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                     uint16_t section)
820b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        : name(name),
821b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          info((binding << 4) | type),
822b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          other(0),
823b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          section(section),
824b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          value(value),
825b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          size(size) {
826b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
827b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
828b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint32_t name;
829b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint8_t info;
830b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint8_t other;
831b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint16_t section;
832b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uintptr_t value;
833b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uintptr_t size;
834b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
835b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif
836b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Write(Writer::Slot<SerializedLayout> s, ELFStringTable* t) {
838b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    // Convert symbol names from strings to indexes in the string table.
839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    s->name = static_cast<uint32_t>(t->Add(name));
840b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    s->value = value;
841b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    s->size = size;
842b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    s->info = info;
843b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    s->other = other;
844b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    s->section = section;
845b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
846b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
847b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
848b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  const char* name;
849b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uintptr_t value;
850b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uintptr_t size;
851b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uint8_t info;
852b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uint8_t other;
853b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uint16_t section;
854b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
855b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
856b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
857b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochclass ELFSymbolTable : public ELFSection {
858b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ELFSymbolTable(const char* name, Zone* zone)
860b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      : ELFSection(name, TYPE_SYMTAB, sizeof(uintptr_t)),
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        locals_(1, zone),
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        globals_(1, zone) {
863b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
864b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
865b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
866b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Align(header->alignment);
867b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    int total_symbols = locals_.length() + globals_.length() + 1;
868b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->offset = w->position();
869b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
870b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Writer::Slot<ELFSymbol::SerializedLayout> symbols =
871b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        w->CreateSlotsHere<ELFSymbol::SerializedLayout>(total_symbols);
872b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
873b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->size = w->position() - header->offset;
874b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
875b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    // String table for this symbol table should follow it in the section table.
876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ELFStringTable* strtab =
877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        static_cast<ELFStringTable*>(w->debug_object()->SectionAt(index() + 1));
878b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    strtab->AttachWriter(w);
879b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    symbols.at(0).set(ELFSymbol::SerializedLayout(0,
880b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                                  0,
881b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                                  0,
882b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                                  ELFSymbol::BIND_LOCAL,
883b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                                  ELFSymbol::TYPE_NOTYPE,
884b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                                  0));
885b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    WriteSymbolsList(&locals_, symbols.at(1), strtab);
886b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    WriteSymbolsList(&globals_, symbols.at(locals_.length() + 1), strtab);
887b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    strtab->DetachWriter();
888b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
889b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Add(const ELFSymbol& symbol, Zone* zone) {
891b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    if (symbol.binding() == ELFSymbol::BIND_LOCAL) {
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      locals_.Add(symbol, zone);
893b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    } else {
894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      globals_.Add(symbol, zone);
895b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
896b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
897b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
898b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch protected:
899b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  virtual void PopulateHeader(Writer::Slot<Header> header) {
900b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    ELFSection::PopulateHeader(header);
901b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    // We are assuming that string table will follow symbol table.
902b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->link = index() + 1;
903b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->info = locals_.length() + 1;
904b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    header->entry_size = sizeof(ELFSymbol::SerializedLayout);
905b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
906b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
907b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
908b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void WriteSymbolsList(const ZoneList<ELFSymbol>* src,
909b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                        Writer::Slot<ELFSymbol::SerializedLayout> dst,
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        ELFStringTable* strtab) {
911b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    for (int i = 0, len = src->length();
912b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         i < len;
913b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch         i++) {
914b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      src->at(i).Write(dst.at(i), strtab);
915b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
916b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
917b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
918b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ZoneList<ELFSymbol> locals_;
919b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ZoneList<ELFSymbol> globals_;
920b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
9213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif  // defined(__ELF)
922b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
923b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass LineInfo : public Malloced {
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LineInfo() : pc_info_(10) {}
927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SetPosition(intptr_t pc, int pos, bool is_statement) {
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AddPCInfo(PCInfo(pc, pos, is_statement));
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  struct PCInfo {
933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PCInfo(intptr_t pc, int pos, bool is_statement)
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        : pc_(pc), pos_(pos), is_statement_(is_statement) {}
935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    intptr_t pc_;
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int pos_;
938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool is_statement_;
939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<PCInfo>* pc_info() { return &pc_info_; }
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AddPCInfo(const PCInfo& pc_info) { pc_info_.Add(pc_info); }
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<PCInfo> pc_info_;
947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
950b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochclass CodeDescription BASE_EMBEDDED {
951b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_X64
9531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  enum StackState {
9541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    POST_RBP_PUSH,
9551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    POST_RBP_SET,
9561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    POST_RBP_POP,
9571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    STACK_STATE_MAX
9581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  };
9591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
9601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
961014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CodeDescription(const char* name, Code* code, SharedFunctionInfo* shared,
962014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                  LineInfo* lineinfo)
963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : name_(name), code_(code), shared_info_(shared), lineinfo_(lineinfo) {}
964b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
9651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const char* name() const {
966b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return name_;
967b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
968b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LineInfo* lineinfo() const { return lineinfo_; }
9701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
971014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_function() const {
972014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Code::Kind kind = code_->kind();
973014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION;
9741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
9751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
976014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool has_scope_info() const { return shared_info_ != NULL; }
9773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ScopeInfo* scope_info() const {
979014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(has_scope_info());
980014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return shared_info_->scope_info();
9813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
9823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
9831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  uintptr_t CodeStart() const {
9841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return reinterpret_cast<uintptr_t>(code_->instruction_start());
985b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
986b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
9871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  uintptr_t CodeEnd() const {
9881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return reinterpret_cast<uintptr_t>(code_->instruction_end());
989b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
990b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
9911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  uintptr_t CodeSize() const {
9921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return CodeEnd() - CodeStart();
9931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
9941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool has_script() {
996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return shared_info_ != NULL && shared_info_->script()->IsScript();
997014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
999014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Script* script() { return Script::cast(shared_info_->script()); }
1000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
10011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool IsLineInfoAvailable() {
1002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return has_script() && script()->source()->IsString() &&
1003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           script()->HasValidSource() && script()->name()->IsString() &&
1004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           lineinfo_ != NULL;
1005b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1006b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_X64
10081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  uintptr_t GetStackStateStartAddress(StackState state) const {
1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(state < STACK_STATE_MAX);
10101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    return stack_state_start_addresses_[state];
10111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
1012b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
10131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void SetStackStateStartAddress(StackState state, uintptr_t addr) {
1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(state < STACK_STATE_MAX);
10151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    stack_state_start_addresses_[state] = addr;
10161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
10171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
10181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1019f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  std::unique_ptr<char[]> GetFilename() {
1020014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return String::cast(script()->name())->ToCString();
1021b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1022b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1023014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int GetScriptLineNumber(int pos) { return script()->GetLineNumber(pos) + 1; }
1024b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
10251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1026b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
1027b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  const char* name_;
1028b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Code* code_;
1029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SharedFunctionInfo* shared_info_;
1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LineInfo* lineinfo_;
1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_X64
10321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  uintptr_t stack_state_start_addresses_[STACK_STATE_MAX];
10331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
1034b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
1035b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
10363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#if defined(__ELF)
1037b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochstatic void CreateSymbolsTable(CodeDescription* desc,
1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Zone* zone,
1039b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                               ELF* elf,
1040b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                               int text_section_index) {
1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ELFSymbolTable* symtab = new(zone) ELFSymbolTable(".symtab", zone);
1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ELFStringTable* strtab = new(zone) ELFStringTable(".strtab");
1043b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1044b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Symbol table should be followed by the linked string table.
1045b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  elf->AddSection(symtab);
1046b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  elf->AddSection(strtab);
1047b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1048b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  symtab->Add(ELFSymbol("V8 Code",
1049b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                        0,
1050b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                        0,
1051b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                        ELFSymbol::BIND_LOCAL,
1052b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                        ELFSymbol::TYPE_FILE,
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        ELFSection::INDEX_ABSOLUTE),
1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              zone);
1055b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
10561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  symtab->Add(ELFSymbol(desc->name(),
1057b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                        0,
10581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                        desc->CodeSize(),
1059b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                        ELFSymbol::BIND_GLOBAL,
1060b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                        ELFSymbol::TYPE_FUNC,
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        text_section_index),
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              zone);
1063b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
10643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif  // defined(__ELF)
1065b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1066b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
10673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass DebugInfoSection : public DebugSection {
1068b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
1069b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  explicit DebugInfoSection(CodeDescription* desc)
10703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#if defined(__ELF)
10713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      : ELFSection(".debug_info", TYPE_PROGBITS, 1),
10723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#else
10733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      : MachOSection("__debug_info",
10743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                     "__DWARF",
10753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                     1,
10763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                     MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
10773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
10783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        desc_(desc) { }
10793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // DWARF2 standard
10813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  enum DWARF2LocationOp {
10823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_OP_reg0 = 0x50,
10833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_OP_reg1 = 0x51,
10843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_OP_reg2 = 0x52,
10853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_OP_reg3 = 0x53,
10863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_OP_reg4 = 0x54,
10873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_OP_reg5 = 0x55,
10883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_OP_reg6 = 0x56,
10893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_OP_reg7 = 0x57,
1090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg8 = 0x58,
1091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg9 = 0x59,
1092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg10 = 0x5a,
1093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg11 = 0x5b,
1094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg12 = 0x5c,
1095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg13 = 0x5d,
1096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg14 = 0x5e,
1097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg15 = 0x5f,
1098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg16 = 0x60,
1099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg17 = 0x61,
1100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg18 = 0x62,
1101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg19 = 0x63,
1102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg20 = 0x64,
1103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg21 = 0x65,
1104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg22 = 0x66,
1105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg23 = 0x67,
1106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg24 = 0x68,
1107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg25 = 0x69,
1108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg26 = 0x6a,
1109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg27 = 0x6b,
1110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg28 = 0x6c,
1111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg29 = 0x6d,
1112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg30 = 0x6e,
1113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DW_OP_reg31 = 0x6f,
11143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_OP_fbreg = 0x91  // 1 param: SLEB128 offset
11153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  };
11163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
11173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  enum DWARF2Encoding {
11183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_ATE_ADDRESS = 0x1,
11193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_ATE_SIGNED = 0x5
11203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  };
1121b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool WriteBodyInternal(Writer* w) {
11233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uintptr_t cu_start = w->position();
1124b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Writer::Slot<uint32_t> size = w->CreateSlotHere<uint32_t>();
1125b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uintptr_t start = w->position();
1126b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Write<uint16_t>(2);  // DWARF version.
1127b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Write<uint32_t>(0);  // Abbreviation table offset.
1128b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Write<uint8_t>(sizeof(intptr_t));
1129b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1130b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->WriteULEB128(1);  // Abbreviation code.
1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    w->WriteString(desc_->GetFilename().get());
11321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    w->Write<intptr_t>(desc_->CodeStart());
11331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
1134b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Write<uint32_t>(0);
11353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
11363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    uint32_t ty_offset = static_cast<uint32_t>(w->position() - cu_start);
11373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    w->WriteULEB128(3);
11383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    w->Write<uint8_t>(kPointerSize);
11393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    w->WriteString("v8value");
11403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (desc_->has_scope_info()) {
1142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ScopeInfo* scope = desc_->scope_info();
11433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(2);
11443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteString(desc_->name());
11453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->Write<intptr_t>(desc_->CodeStart());
11463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
11473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      Writer::Slot<uint32_t> fb_block_size = w->CreateSlotHere<uint32_t>();
11483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      uintptr_t fb_block_start = w->position();
1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
11503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->Write<uint8_t>(DW_OP_reg5);  // The frame pointer's here on ia32
1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#elif V8_TARGET_ARCH_X64
11523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->Write<uint8_t>(DW_OP_reg6);  // and here on x64.
1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#elif V8_TARGET_ARCH_ARM
1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNIMPLEMENTED();
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#elif V8_TARGET_ARCH_MIPS
1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNIMPLEMENTED();
1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#elif V8_TARGET_ARCH_MIPS64
1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      UNIMPLEMENTED();
1159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#elif V8_TARGET_ARCH_PPC64 && V8_OS_LINUX
1160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      w->Write<uint8_t>(DW_OP_reg31);  // The frame pointer is here on PPC64.
11613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#elif V8_TARGET_ARCH_S390
11623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      w->Write<uint8_t>(DW_OP_reg11);  // The frame pointer's here on S390.
11633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#else
11643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#error Unsupported target architecture.
11653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
11663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start));
11673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int params = scope->ParameterCount();
1169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int slots = scope->StackLocalCount();
1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int context_slots = scope->ContextLocalCount();
11713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // The real slot ID is internal_slots + context_slot_id.
11723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int internal_slots = Context::MIN_CONTEXT_SLOTS;
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int locals = scope->StackLocalCount();
11743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int current_abbreviation = 4;
11753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
11763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      for (int param = 0; param < params; ++param) {
11773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->WriteULEB128(current_abbreviation++);
11783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->WriteString(
1179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            scope->ParameterName(param)->ToCString(DISALLOW_NULLS).get());
11803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->Write<uint32_t>(ty_offset);
11813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
11823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        uintptr_t block_start = w->position();
11833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->Write<uint8_t>(DW_OP_fbreg);
11843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->WriteSLEB128(
11853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          JavaScriptFrameConstants::kLastParameterOffset +
11863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch              kPointerSize * (params - param - 1));
11873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        block_size.set(static_cast<uint32_t>(w->position() - block_start));
11883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
11893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
11903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      EmbeddedVector<char, 256> buffer;
11913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      StringBuilder builder(buffer.start(), buffer.length());
11923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
11933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      for (int slot = 0; slot < slots; ++slot) {
11943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->WriteULEB128(current_abbreviation++);
11953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        builder.Reset();
11963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        builder.AddFormatted("slot%d", slot);
11973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->WriteString(builder.Finalize());
11983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
11993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
12003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // See contexts.h for more information.
1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(Context::MIN_CONTEXT_SLOTS == 4);
1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(Context::CLOSURE_INDEX == 0);
1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(Context::PREVIOUS_INDEX == 1);
1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(Context::EXTENSION_INDEX == 2);
1205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DCHECK(Context::NATIVE_CONTEXT_INDEX == 3);
12063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(current_abbreviation++);
12073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteString(".closure");
12083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(current_abbreviation++);
12093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteString(".previous");
12103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(current_abbreviation++);
12113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteString(".extension");
12123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(current_abbreviation++);
1213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      w->WriteString(".native_context");
12143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
12153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      for (int context_slot = 0;
12163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           context_slot < context_slots;
12173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           ++context_slot) {
12183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->WriteULEB128(current_abbreviation++);
12193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        builder.Reset();
12203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        builder.AddFormatted("context_slot%d", context_slot + internal_slots);
12213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->WriteString(builder.Finalize());
12223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
12233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
12243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      for (int local = 0; local < locals; ++local) {
12253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->WriteULEB128(current_abbreviation++);
12263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->WriteString(
1227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            scope->StackLocalName(local)->ToCString(DISALLOW_NULLS).get());
12283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->Write<uint32_t>(ty_offset);
12293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
12303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        uintptr_t block_start = w->position();
12313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->Write<uint8_t>(DW_OP_fbreg);
12323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->WriteSLEB128(
12333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          JavaScriptFrameConstants::kLocal0Offset -
12343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch              kPointerSize * local);
12353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        block_size.set(static_cast<uint32_t>(w->position() - block_start));
12363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
12373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
12383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      {
12393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->WriteULEB128(current_abbreviation++);
12403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->WriteString("__function");
12413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->Write<uint32_t>(ty_offset);
12423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
12433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        uintptr_t block_start = w->position();
12443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->Write<uint8_t>(DW_OP_fbreg);
12453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->WriteSLEB128(JavaScriptFrameConstants::kFunctionOffset);
12463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        block_size.set(static_cast<uint32_t>(w->position() - block_start));
12473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
12483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
12493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      {
12503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->WriteULEB128(current_abbreviation++);
12513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->WriteString("__context");
12523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->Write<uint32_t>(ty_offset);
12533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
12543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        uintptr_t block_start = w->position();
12553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->Write<uint8_t>(DW_OP_fbreg);
12563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        w->WriteSLEB128(StandardFrameConstants::kContextOffset);
12573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        block_size.set(static_cast<uint32_t>(w->position() - block_start));
12583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      w->WriteULEB128(0);  // Terminate the sub program.
12613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
12623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    w->WriteULEB128(0);  // Terminate the compile unit.
1264b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    size.set(static_cast<uint32_t>(w->position() - start));
1265b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return true;
1266b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1267b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1268b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
1269b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  CodeDescription* desc_;
1270b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
1271b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1272b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
12733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass DebugAbbrevSection : public DebugSection {
1274b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
12753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  explicit DebugAbbrevSection(CodeDescription* desc)
12763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#ifdef __ELF
12773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      : ELFSection(".debug_abbrev", TYPE_PROGBITS, 1),
12783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#else
12793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      : MachOSection("__debug_abbrev",
12803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                     "__DWARF",
12813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                     1,
12823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                     MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
12833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
12843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        desc_(desc) { }
1285b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1286b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // DWARF2 standard, figure 14.
1287b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  enum DWARF2Tags {
12883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_TAG_FORMAL_PARAMETER = 0x05,
12893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_TAG_POINTER_TYPE = 0xf,
12903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_TAG_COMPILE_UNIT = 0x11,
12913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_TAG_STRUCTURE_TYPE = 0x13,
12923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_TAG_BASE_TYPE = 0x24,
12933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_TAG_SUBPROGRAM = 0x2e,
12943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_TAG_VARIABLE = 0x34
1295b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
1296b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1297b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // DWARF2 standard, figure 16.
1298b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  enum DWARF2ChildrenDetermination {
1299b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    DW_CHILDREN_NO = 0,
1300b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    DW_CHILDREN_YES = 1
1301b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
1302b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1303b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // DWARF standard, figure 17.
1304b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  enum DWARF2Attribute {
13053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_AT_LOCATION = 0x2,
1306b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    DW_AT_NAME = 0x3,
13073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_AT_BYTE_SIZE = 0xb,
1308b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    DW_AT_STMT_LIST = 0x10,
1309b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    DW_AT_LOW_PC = 0x11,
13103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_AT_HIGH_PC = 0x12,
13113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_AT_ENCODING = 0x3e,
13123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_AT_FRAME_BASE = 0x40,
13133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_AT_TYPE = 0x49
1314b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
1315b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1316b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // DWARF2 standard, figure 19.
1317b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  enum DWARF2AttributeForm {
1318b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    DW_FORM_ADDR = 0x1,
13193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_FORM_BLOCK4 = 0x4,
1320b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    DW_FORM_STRING = 0x8,
13213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_FORM_DATA4 = 0x6,
13223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_FORM_BLOCK = 0x9,
13233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_FORM_DATA1 = 0xb,
13243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_FORM_FLAG = 0xc,
13253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DW_FORM_REF4 = 0x13
1326b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
1327b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
13283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void WriteVariableAbbreviation(Writer* w,
13293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 int abbreviation_code,
13303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 bool has_value,
13313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                 bool is_parameter) {
13323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    w->WriteULEB128(abbreviation_code);
13333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    w->WriteULEB128(is_parameter ? DW_TAG_FORMAL_PARAMETER : DW_TAG_VARIABLE);
13343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    w->Write<uint8_t>(DW_CHILDREN_NO);
13353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    w->WriteULEB128(DW_AT_NAME);
13363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    w->WriteULEB128(DW_FORM_STRING);
13373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (has_value) {
13383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_AT_TYPE);
13393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_FORM_REF4);
13403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_AT_LOCATION);
13413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_FORM_BLOCK4);
13423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
13433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    w->WriteULEB128(0);
13443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    w->WriteULEB128(0);
13453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
13463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool WriteBodyInternal(Writer* w) {
13483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int current_abbreviation = 1;
1349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    bool extra_info = desc_->has_scope_info();
1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(desc_->IsLineInfoAvailable());
13513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    w->WriteULEB128(current_abbreviation++);
1352b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->WriteULEB128(DW_TAG_COMPILE_UNIT);
13533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    w->Write<uint8_t>(extra_info ? DW_CHILDREN_YES : DW_CHILDREN_NO);
1354b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->WriteULEB128(DW_AT_NAME);
1355b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->WriteULEB128(DW_FORM_STRING);
1356b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->WriteULEB128(DW_AT_LOW_PC);
1357b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->WriteULEB128(DW_FORM_ADDR);
1358b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->WriteULEB128(DW_AT_HIGH_PC);
1359b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->WriteULEB128(DW_FORM_ADDR);
1360b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->WriteULEB128(DW_AT_STMT_LIST);
1361b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->WriteULEB128(DW_FORM_DATA4);
1362b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->WriteULEB128(0);
1363b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->WriteULEB128(0);
13643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
13653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (extra_info) {
1366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ScopeInfo* scope = desc_->scope_info();
1367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int params = scope->ParameterCount();
1368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int slots = scope->StackLocalCount();
1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int context_slots = scope->ContextLocalCount();
13703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // The real slot ID is internal_slots + context_slot_id.
13713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int internal_slots = Context::MIN_CONTEXT_SLOTS;
1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int locals = scope->StackLocalCount();
1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Total children is params + slots + context_slots + internal_slots +
1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // locals + 2 (__function and __context).
13753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
13763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // The extra duplication below seems to be necessary to keep
13773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // gdb from getting upset on OSX.
13783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(current_abbreviation++);  // Abbreviation code.
13793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_TAG_SUBPROGRAM);
1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      w->Write<uint8_t>(DW_CHILDREN_YES);
13813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_AT_NAME);
13823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_FORM_STRING);
13833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_AT_LOW_PC);
13843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_FORM_ADDR);
13853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_AT_HIGH_PC);
13863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_FORM_ADDR);
13873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_AT_FRAME_BASE);
13883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_FORM_BLOCK4);
13893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(0);
13903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(0);
13913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
13923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(current_abbreviation++);
13933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_TAG_STRUCTURE_TYPE);
13943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->Write<uint8_t>(DW_CHILDREN_NO);
13953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_AT_BYTE_SIZE);
13963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_FORM_DATA1);
13973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_AT_NAME);
13983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(DW_FORM_STRING);
13993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(0);
14003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      w->WriteULEB128(0);
14013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      for (int param = 0; param < params; ++param) {
14033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        WriteVariableAbbreviation(w, current_abbreviation++, true, true);
14043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
14053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      for (int slot = 0; slot < slots; ++slot) {
14073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        WriteVariableAbbreviation(w, current_abbreviation++, false, false);
14083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
14093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      for (int internal_slot = 0;
14113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           internal_slot < internal_slots;
14123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           ++internal_slot) {
14133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        WriteVariableAbbreviation(w, current_abbreviation++, false, false);
14143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
14153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      for (int context_slot = 0;
14173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           context_slot < context_slots;
14183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           ++context_slot) {
14193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        WriteVariableAbbreviation(w, current_abbreviation++, false, false);
14203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
14213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      for (int local = 0; local < locals; ++local) {
14233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        WriteVariableAbbreviation(w, current_abbreviation++, true, false);
14243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
14253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // The function.
14273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      WriteVariableAbbreviation(w, current_abbreviation++, true, false);
14283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // The context.
14303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      WriteVariableAbbreviation(w, current_abbreviation++, true, false);
14313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      w->WriteULEB128(0);  // Terminate the sibling list.
14333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
14343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    w->WriteULEB128(0);  // Terminate the table.
1436b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return true;
1437b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
14383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
14393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private:
14403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CodeDescription* desc_;
1441b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
1442b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1443b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
14443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass DebugLineSection : public DebugSection {
1445b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch public:
1446b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  explicit DebugLineSection(CodeDescription* desc)
14473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#ifdef __ELF
1448b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      : ELFSection(".debug_line", TYPE_PROGBITS, 1),
14493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#else
14503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      : MachOSection("__debug_line",
14513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                     "__DWARF",
14523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                     1,
14533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                     MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
14543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
1455b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        desc_(desc) { }
1456b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1457b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // DWARF2 standard, figure 34.
1458b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  enum DWARF2Opcodes {
1459b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    DW_LNS_COPY = 1,
1460b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    DW_LNS_ADVANCE_PC = 2,
1461b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    DW_LNS_ADVANCE_LINE = 3,
1462b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    DW_LNS_SET_FILE = 4,
1463b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    DW_LNS_SET_COLUMN = 5,
1464b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    DW_LNS_NEGATE_STMT = 6
1465b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
1466b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1467b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // DWARF2 standard, figure 35.
1468b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  enum DWARF2ExtendedOpcode {
1469b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    DW_LNE_END_SEQUENCE = 1,
1470b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    DW_LNE_SET_ADDRESS = 2,
1471b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    DW_LNE_DEFINE_FILE = 3
1472b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
1473b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool WriteBodyInternal(Writer* w) {
1475b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    // Write prologue.
1476b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Writer::Slot<uint32_t> total_length = w->CreateSlotHere<uint32_t>();
1477b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uintptr_t start = w->position();
1478b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1479e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Used for special opcodes
1480e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    const int8_t line_base = 1;
1481e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    const uint8_t line_range = 7;
1482e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    const int8_t max_line_incr = (line_base + line_range - 1);
1483e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    const uint8_t opcode_base = DW_LNS_NEGATE_STMT + 1;
1484e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1485b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Write<uint16_t>(2);  // Field version.
1486b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Writer::Slot<uint32_t> prologue_length = w->CreateSlotHere<uint32_t>();
1487b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uintptr_t prologue_start = w->position();
1488b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Write<uint8_t>(1);  // Field minimum_instruction_length.
1489b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Write<uint8_t>(1);  // Field default_is_stmt.
1490e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    w->Write<int8_t>(line_base);  // Field line_base.
1491e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    w->Write<uint8_t>(line_range);  // Field line_range.
1492e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    w->Write<uint8_t>(opcode_base);  // Field opcode_base.
1493b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Write<uint8_t>(0);  // DW_LNS_COPY operands count.
1494b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Write<uint8_t>(1);  // DW_LNS_ADVANCE_PC operands count.
1495b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Write<uint8_t>(1);  // DW_LNS_ADVANCE_LINE operands count.
1496b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Write<uint8_t>(1);  // DW_LNS_SET_FILE operands count.
1497b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Write<uint8_t>(1);  // DW_LNS_SET_COLUMN operands count.
1498b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Write<uint8_t>(0);  // DW_LNS_NEGATE_STMT operands count.
1499b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Write<uint8_t>(0);  // Empty include_directories sequence.
1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    w->WriteString(desc_->GetFilename().get());  // File name.
1501b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->WriteULEB128(0);  // Current directory.
1502b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->WriteULEB128(0);  // Unknown modification time.
1503b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->WriteULEB128(0);  // Unknown file size.
1504b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Write<uint8_t>(0);
1505b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    prologue_length.set(static_cast<uint32_t>(w->position() - prologue_start));
1506b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1507b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS, sizeof(intptr_t));
15081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    w->Write<intptr_t>(desc_->CodeStart());
1509e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    w->Write<uint8_t>(DW_LNS_COPY);
1510b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1511b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    intptr_t pc = 0;
1512b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    intptr_t line = 1;
1513b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    bool is_statement = true;
1514b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    List<LineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info();
1516b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    pc_info->Sort(&ComparePCInfo);
1517e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1518e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    int pc_info_length = pc_info->length();
1519e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    for (int i = 0; i < pc_info_length; i++) {
1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      LineInfo::PCInfo* info = &pc_info->at(i);
1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(info->pc_ >= pc);
1522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Reduce bloating in the debug line table by removing duplicate line
1524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // entries (per DWARF2 standard).
1525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      intptr_t  new_line = desc_->GetScriptLineNumber(info->pos_);
1526e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (new_line == line) {
1527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        continue;
1528b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      }
1529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Mark statement boundaries.  For a better debugging experience, mark
1531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // the last pc address in the function as a statement (e.g. "}"), so that
1532e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // a user can see the result of the last line executed in the function,
1533e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // should control reach the end.
1534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if ((i+1) == pc_info_length) {
1535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        if (!is_statement) {
1536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1537e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        }
1538e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else if (is_statement != info->is_statement_) {
1539b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1540b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        is_statement = !is_statement;
1541b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      }
1542e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Generate special opcodes, if possible.  This results in more compact
1544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // debug line tables.  See the DWARF 2.0 standard to learn more about
1545e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // special opcodes.
1546e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      uintptr_t pc_diff = info->pc_ - pc;
1547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      intptr_t line_diff = new_line - line;
1548e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1549e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Compute special opcode (see DWARF 2.0 standard)
1550e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      intptr_t special_opcode = (line_diff - line_base) +
1551e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                (line_range * pc_diff) + opcode_base;
1552e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1553e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // If special_opcode is less than or equal to 255, it can be used as a
1554e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // special opcode.  If line_diff is larger than the max line increment
1555e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // allowed for a special opcode, or if line_diff is less than the minimum
1556e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // line that can be added to the line register (i.e. line_base), then
1557e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // special_opcode can't be used.
1558e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if ((special_opcode >= opcode_base) && (special_opcode <= 255) &&
1559e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch          (line_diff <= max_line_incr) && (line_diff >= line_base)) {
1560e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        w->Write<uint8_t>(special_opcode);
1561e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      } else {
1562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1563e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        w->WriteSLEB128(pc_diff);
1564e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        w->Write<uint8_t>(DW_LNS_ADVANCE_LINE);
1565e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        w->WriteSLEB128(line_diff);
1566b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        w->Write<uint8_t>(DW_LNS_COPY);
1567b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      }
1568e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
1569e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Increment the pc and line operands.
1570e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      pc += pc_diff;
1571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      line += line_diff;
1572b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
1573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // Advance the pc to the end of the routine, since the end sequence opcode
1574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // requires this.
1575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1576e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    w->WriteSLEB128(desc_->CodeSize() - pc);
1577b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    WriteExtendedOpcode(w, DW_LNE_END_SEQUENCE, 0);
1578b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    total_length.set(static_cast<uint32_t>(w->position() - start));
1579b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return true;
1580b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1581b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1582b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch private:
1583b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void WriteExtendedOpcode(Writer* w,
1584b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           DWARF2ExtendedOpcode op,
1585b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                           size_t operands_size) {
1586b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Write<uint8_t>(0);
1587b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->WriteULEB128(operands_size + 1);
1588b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    w->Write<uint8_t>(op);
1589b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1590b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static int ComparePCInfo(const LineInfo::PCInfo* a,
1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           const LineInfo::PCInfo* b) {
1593b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    if (a->pc_ == b->pc_) {
1594b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      if (a->is_statement_ != b->is_statement_) {
1595b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        return b->is_statement_ ? +1 : -1;
1596b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      }
1597b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      return 0;
1598b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    } else if (a->pc_ > b->pc_) {
1599b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      return +1;
1600b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    } else {
1601b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      return -1;
1602b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
1603b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1604b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1605b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  CodeDescription* desc_;
1606b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch};
1607b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1608b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_X64
16101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
16113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass UnwindInfoSection : public DebugSection {
16121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public:
16133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit UnwindInfoSection(CodeDescription* desc);
1614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual bool WriteBodyInternal(Writer* w);
16151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
16163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int WriteCIE(Writer* w);
16173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void WriteFDE(Writer* w, int);
16181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
16193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void WriteFDEStateOnEntry(Writer* w);
16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void WriteFDEStateAfterRBPPush(Writer* w);
16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void WriteFDEStateAfterRBPSet(Writer* w);
16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void WriteFDEStateAfterRBPPop(Writer* w);
16231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void WriteLength(Writer* w,
16251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                   Writer::Slot<uint32_t>* length_slot,
16261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                   int initial_position);
16271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
16281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private:
16293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CodeDescription* desc_;
16301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
16311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // DWARF3 Specification, Table 7.23
16321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  enum CFIInstructions {
16331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_ADVANCE_LOC = 0x40,
16341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_OFFSET = 0x80,
16351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_RESTORE = 0xC0,
16361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_NOP = 0x00,
16371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_SET_LOC = 0x01,
16381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_ADVANCE_LOC1 = 0x02,
16391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_ADVANCE_LOC2 = 0x03,
16401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_ADVANCE_LOC4 = 0x04,
16411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_OFFSET_EXTENDED = 0x05,
16421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_RESTORE_EXTENDED = 0x06,
16431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_UNDEFINED = 0x07,
16441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_SAME_VALUE = 0x08,
16451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_REGISTER = 0x09,
16461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_REMEMBER_STATE = 0x0A,
16471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_RESTORE_STATE = 0x0B,
16481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_DEF_CFA = 0x0C,
16491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_DEF_CFA_REGISTER = 0x0D,
16501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_DEF_CFA_OFFSET = 0x0E,
16511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
16521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_DEF_CFA_EXPRESSION = 0x0F,
16531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_EXPRESSION = 0x10,
16541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_OFFSET_EXTENDED_SF = 0x11,
16551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_DEF_CFA_SF = 0x12,
16561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_DEF_CFA_OFFSET_SF = 0x13,
16571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_VAL_OFFSET = 0x14,
16581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_VAL_OFFSET_SF = 0x15,
16591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DW_CFA_VAL_EXPRESSION = 0x16
16601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  };
16611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
16621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // System V ABI, AMD64 Supplement, Version 0.99.5, Figure 3.36
16631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  enum RegisterMapping {
16641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Only the relevant ones have been added to reduce clutter.
16651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    AMD64_RBP = 6,
16661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    AMD64_RSP = 7,
16671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    AMD64_RA = 16
16681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  };
16691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
16701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  enum CFIConstants {
16711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    CIE_ID = 0,
16721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    CIE_VERSION = 1,
16731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    CODE_ALIGN_FACTOR = 1,
16741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DATA_ALIGN_FACTOR = 1,
16751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    RETURN_ADDRESS_REGISTER = AMD64_RA
16761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  };
16771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
16781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
16791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
16803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid UnwindInfoSection::WriteLength(Writer* w,
16811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    Writer::Slot<uint32_t>* length_slot,
16821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    int initial_position) {
16831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  uint32_t align = (w->position() - initial_position) % kPointerSize;
16841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
16851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (align != 0) {
16861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    for (uint32_t i = 0; i < (kPointerSize - align); i++) {
16871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      w->Write<uint8_t>(DW_CFA_NOP);
16881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
16891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
16901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((w->position() - initial_position) % kPointerSize == 0);
1692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  length_slot->set(static_cast<uint32_t>(w->position() - initial_position));
16931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
16941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
16951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
16963ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochUnwindInfoSection::UnwindInfoSection(CodeDescription* desc)
16973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#ifdef __ELF
16983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1),
16993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#else
17003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    : MachOSection("__eh_frame", "__TEXT", sizeof(uintptr_t),
17013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                   MachOSection::S_REGULAR),
17023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
17033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      desc_(desc) { }
17041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint UnwindInfoSection::WriteCIE(Writer* w) {
17061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>();
1707014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t cie_position = static_cast<uint32_t>(w->position());
17081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Write out the CIE header. Currently no 'common instructions' are
17101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // emitted onto the CIE; every FDE has its own set of instructions.
17111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint32_t>(CIE_ID);
17131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint8_t>(CIE_VERSION);
17141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint8_t>(0);  // Null augmentation string.
17151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->WriteSLEB128(CODE_ALIGN_FACTOR);
17161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->WriteSLEB128(DATA_ALIGN_FACTOR);
17171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint8_t>(RETURN_ADDRESS_REGISTER);
17181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  WriteLength(w, &cie_length_slot, cie_position);
17201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return cie_position;
17221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
17231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid UnwindInfoSection::WriteFDE(Writer* w, int cie_position) {
17261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The only FDE for this function. The CFA is the current RBP.
17271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<uint32_t>();
1728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int fde_position = static_cast<uint32_t>(w->position());
17291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<int32_t>(fde_position - cie_position + 4);
17301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uintptr_t>(desc_->CodeStart());
17321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uintptr_t>(desc_->CodeSize());
17331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  WriteFDEStateOnEntry(w);
17351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  WriteFDEStateAfterRBPPush(w);
17361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  WriteFDEStateAfterRBPSet(w);
17371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  WriteFDEStateAfterRBPPop(w);
17381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  WriteLength(w, &fde_length_slot, fde_position);
17401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
17411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid UnwindInfoSection::WriteFDEStateOnEntry(Writer* w) {
17441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The first state, just after the control has been transferred to the the
17451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // function.
17461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // RBP for this function will be the value of RSP after pushing the RBP
17481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // for the previous function. The previous RBP has not been pushed yet.
17491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
17501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->WriteULEB128(AMD64_RSP);
17511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->WriteSLEB128(-kPointerSize);
17521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The RA is stored at location CFA + kCallerPCOffset. This is an invariant,
17541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // and hence omitted from the next states.
17551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
17561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->WriteULEB128(AMD64_RA);
17571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->WriteSLEB128(StandardFrameConstants::kCallerPCOffset);
17581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The RBP of the previous function is still in RBP.
17601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint8_t>(DW_CFA_SAME_VALUE);
17611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->WriteULEB128(AMD64_RBP);
17621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Last location described by this entry.
17641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint8_t>(DW_CFA_SET_LOC);
17651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint64_t>(
17661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_PUSH));
17671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
17681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer* w) {
17711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The second state, just after RBP has been pushed.
17721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // RBP / CFA for this function is now the current RSP, so just set the
17741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // offset from the previous rule (from -8) to 0.
17751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint8_t>(DW_CFA_DEF_CFA_OFFSET);
17761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->WriteULEB128(0);
17771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The previous RBP is stored at CFA + kCallerFPOffset. This is an invariant
17791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // in this and the next state, and hence omitted in the next state.
17801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
17811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->WriteULEB128(AMD64_RBP);
17821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
17831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Last location described by this entry.
17851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint8_t>(DW_CFA_SET_LOC);
17861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint64_t>(
17871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_SET));
17881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
17891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer* w) {
17921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The third state, after the RBP has been set.
17931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The CFA can now directly be set to RBP.
17951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint8_t>(DW_CFA_DEF_CFA);
17961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->WriteULEB128(AMD64_RBP);
17971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->WriteULEB128(0);
17981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
17991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Last location described by this entry.
18001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint8_t>(DW_CFA_SET_LOC);
18011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint64_t>(
18021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_POP));
18031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
18041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer* w) {
18071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The fourth (final) state. The RBP has been popped (just before issuing a
18081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // return).
18091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The CFA can is now calculated in the same way as in the first state.
18111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
18121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->WriteULEB128(AMD64_RSP);
18131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->WriteSLEB128(-kPointerSize);
18141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The RBP
18161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
18171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->WriteULEB128(AMD64_RBP);
18181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
18191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Last location described by this entry.
18211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint8_t>(DW_CFA_SET_LOC);
18221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  w->Write<uint64_t>(desc_->CodeEnd());
18231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
18241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool UnwindInfoSection::WriteBodyInternal(Writer* w) {
18271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  uint32_t cie_position = WriteCIE(w);
18281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  WriteFDE(w, cie_position);
18291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return true;
18301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
18311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
18331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif  // V8_TARGET_ARCH_X64
18341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void CreateDWARFSections(CodeDescription* desc,
1836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                Zone* zone,
1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                DebugObject* obj) {
18381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (desc->IsLineInfoAvailable()) {
1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj->AddSection(new(zone) DebugInfoSection(desc));
1840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj->AddSection(new(zone) DebugAbbrevSection(desc));
1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj->AddSection(new(zone) DebugLineSection(desc));
1842b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_X64
1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  obj->AddSection(new(zone) UnwindInfoSection(desc));
18451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
1846b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
1847b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1848b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1849b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// -------------------------------------------------------------------
1850b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Binary GDB JIT Interface as described in
1851b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch//   http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html
1852b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochextern "C" {
1853b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  typedef enum {
1854b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    JIT_NOACTION = 0,
1855b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    JIT_REGISTER_FN,
1856b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    JIT_UNREGISTER_FN
1857b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  } JITAction;
1858b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1859b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  struct JITCodeEntry {
1860b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    JITCodeEntry* next_;
1861b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    JITCodeEntry* prev_;
1862b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Address symfile_addr_;
1863b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint64_t symfile_size_;
1864b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
1865b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1866b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  struct JITDescriptor {
1867b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint32_t version_;
1868b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    uint32_t action_flag_;
18693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JITCodeEntry* relevant_entry_;
18703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JITCodeEntry* first_entry_;
1871b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  };
1872b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1873b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // GDB will place breakpoint into this function.
1874b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // To prevent GCC from inlining or removing it we place noinline attribute
1875b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // and inline assembler statement inside.
1876b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void __attribute__((noinline)) __jit_debug_register_code() {
1877b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __asm__("");
1878b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1879b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1880b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // GDB will inspect contents of this descriptor.
1881b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Static initialization is necessary to prevent GDB from seeing
1882b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // uninitialized descriptor.
1883b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  JITDescriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
18843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
18853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#ifdef OBJECT_PRINT
1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void __gdb_print_v8_object(Object* object) {
1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    OFStream os(stdout);
1888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    object->Print(os);
1889958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    os << std::flush;
18903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
18913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
1892b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
1893b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1894b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1895b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochstatic JITCodeEntry* CreateCodeEntry(Address symfile_addr,
1896b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                     uintptr_t symfile_size) {
1897b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  JITCodeEntry* entry = static_cast<JITCodeEntry*>(
1898b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      malloc(sizeof(JITCodeEntry) + symfile_size));
1899b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1900b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  entry->symfile_addr_ = reinterpret_cast<Address>(entry + 1);
1901b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  entry->symfile_size_ = symfile_size;
1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemCopy(entry->symfile_addr_, symfile_addr, symfile_size);
1903b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1904b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  entry->prev_ = entry->next_ = NULL;
1905b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1906b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  return entry;
1907b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
1908b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1909b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1910b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochstatic void DestroyCodeEntry(JITCodeEntry* entry) {
1911b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  free(entry);
1912b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
1913b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1914b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void RegisterCodeEntry(JITCodeEntry* entry) {
1916b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  entry->next_ = __jit_debug_descriptor.first_entry_;
1917b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (entry->next_ != NULL) entry->next_->prev_ = entry;
1918b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __jit_debug_descriptor.first_entry_ =
1919b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      __jit_debug_descriptor.relevant_entry_ = entry;
1920b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1921b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
1922b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __jit_debug_register_code();
1923b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
1924b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1925b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1926b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochstatic void UnregisterCodeEntry(JITCodeEntry* entry) {
1927b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (entry->prev_ != NULL) {
1928b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    entry->prev_->next_ = entry->next_;
1929b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  } else {
1930b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    __jit_debug_descriptor.first_entry_ = entry->next_;
1931b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1932b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1933b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (entry->next_ != NULL) {
1934b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    entry->next_->prev_ = entry->prev_;
1935b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
1936b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1937b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __jit_debug_descriptor.relevant_entry_ = entry;
1938b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
1939b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  __jit_debug_register_code();
1940b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
1941b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1942b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic JITCodeEntry* CreateELFObject(CodeDescription* desc, Isolate* isolate) {
19443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#ifdef __MACH_O
1945c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Zone zone(isolate->allocator(), ZONE_NAME);
1946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MachO mach_o(&zone);
19473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Writer w(&mach_o);
19483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  mach_o.AddSection(new(&zone) MachOTextSection(kCodeAlignment,
1950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                desc->CodeStart(),
1951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                desc->CodeSize()));
19523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CreateDWARFSections(desc, &zone, &mach_o);
1954b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
19553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  mach_o.Write(&w, desc->CodeStart(), desc->CodeSize());
19563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#else
1957c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Zone zone(isolate->allocator(), ZONE_NAME);
1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ELF elf(&zone);
1959b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Writer w(&elf);
1960b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1961b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int text_section_index = elf.AddSection(
1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      new(&zone) FullHeaderELFSection(
1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ".text",
1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ELFSection::TYPE_NOBITS,
1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          kCodeAlignment,
1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          desc->CodeStart(),
1967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          0,
1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          desc->CodeSize(),
1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC));
1970b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CreateSymbolsTable(desc, &zone, &elf, text_section_index);
1972b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CreateDWARFSections(desc, &zone, &elf);
1974b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1975b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  elf.Write(&w);
19763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
1977b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1978b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  return CreateCodeEntry(w.buffer(), w.position());
1979b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
1980b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1981b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct AddressRange {
1983014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Address start;
1984014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Address end;
1985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
1986b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct SplayTreeConfig {
1988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  typedef AddressRange Key;
1989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  typedef JITCodeEntry* Value;
1990014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const AddressRange kNoKey;
1991014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static Value NoValue() { return NULL; }
1992014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static int Compare(const AddressRange& a, const AddressRange& b) {
1993014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // ptrdiff_t probably doesn't fit in an int.
1994014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (a.start < b.start) return -1;
1995014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (a.start == b.start) return 0;
1996014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return 1;
1997e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
1998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
1999b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst AddressRange SplayTreeConfig::kNoKey = {0, 0};
2001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtypedef SplayTree<SplayTreeConfig> CodeMap;
2002b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic CodeMap* GetCodeMap() {
2004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static CodeMap* code_map = NULL;
2005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (code_map == NULL) code_map = new CodeMap();
2006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return code_map;
2007b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
2008b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2009b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic uint32_t HashCodeAddress(Address addr) {
2011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const uintptr_t kGoldenRatio = 2654435761u;
2012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uintptr_t offset = OffsetFrom(addr);
2013014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return static_cast<uint32_t>((offset >> kCodeAlignmentBits) * kGoldenRatio);
2014b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
2015b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
201613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochstatic base::HashMap* GetLineMap() {
201713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static base::HashMap* line_map = NULL;
201813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (line_map == NULL) {
2019f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    line_map = new base::HashMap();
202013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
2021014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return line_map;
2022b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
2023b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2024b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void PutLineInfo(Address addr, LineInfo* info) {
202613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  base::HashMap* line_map = GetLineMap();
202713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  base::HashMap::Entry* e =
202813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      line_map->LookupOrInsert(addr, HashCodeAddress(addr));
2029014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (e->value != NULL) delete static_cast<LineInfo*>(e->value);
2030014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  e->value = info;
2031b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
2032b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2033b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2034014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic LineInfo* GetLineInfo(Address addr) {
2035014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void* value = GetLineMap()->Remove(addr, HashCodeAddress(addr));
2036014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return static_cast<LineInfo*>(value);
20371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
20381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void AddUnwindInfo(CodeDescription* desc) {
2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_X64
2042014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (desc->is_function()) {
20431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // To avoid propagating unwinding information through
2044e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // compilation pipeline we use an approximation.
2045e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    // For most use cases this should not affect usability.
20461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    static const int kFramePointerPushOffset = 1;
20471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    static const int kFramePointerSetOffset = 4;
20481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    static const int kFramePointerPopOffset = -3;
20491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
20501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    uintptr_t frame_pointer_push_address =
20511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        desc->CodeStart() + kFramePointerPushOffset;
20521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
20531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    uintptr_t frame_pointer_set_address =
20541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        desc->CodeStart() + kFramePointerSetOffset;
20551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
20561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    uintptr_t frame_pointer_pop_address =
20571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        desc->CodeEnd() + kFramePointerPopOffset;
20581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
20591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
20601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    frame_pointer_push_address);
20611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
20621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    frame_pointer_set_address);
20631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
20641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    frame_pointer_pop_address);
2065b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  } else {
20661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
20671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    desc->CodeStart());
20681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
20691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    desc->CodeStart());
20701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
20711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                    desc->CodeEnd());
2072b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
20731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif  // V8_TARGET_ARCH_X64
2074b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
2075b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2076b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic base::LazyMutex mutex = LAZY_MUTEX_INITIALIZER;
20788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
20798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2080014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Remove entries from the splay tree that intersect the given address range,
2081014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// and deregister them from GDB.
2082014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void RemoveJITCodeEntries(CodeMap* map, const AddressRange& range) {
2083014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(range.start < range.end);
2084014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CodeMap::Locator cur;
2085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (map->FindGreatestLessThan(range, &cur) || map->FindLeast(&cur)) {
2086014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Skip entries that are entirely less than the range of interest.
2087014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    while (cur.key().end <= range.start) {
2088014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // CodeMap::FindLeastGreaterThan succeeds for entries whose key is greater
2089014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // than _or equal to_ the given key, so we have to advance our key to get
2090014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // the next one.
2091014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      AddressRange new_key;
2092014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      new_key.start = cur.key().end;
2093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      new_key.end = 0;
2094014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!map->FindLeastGreaterThan(new_key, &cur)) return;
2095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Evict intersecting ranges.
2097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    while (cur.key().start < range.end) {
2098014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      AddressRange old_range = cur.key();
2099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      JITCodeEntry* old_entry = cur.value();
2100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      UnregisterCodeEntry(old_entry);
2102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DestroyCodeEntry(old_entry);
2103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CHECK(map->Remove(old_range));
2105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!map->FindLeastGreaterThan(old_range, &cur)) return;
2106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Insert the entry into the splay tree and register it with GDB.
2112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void AddJITCodeEntry(CodeMap* map, const AddressRange& range,
2113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                            JITCodeEntry* entry, bool dump_if_enabled,
2114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                            const char* name_hint) {
2115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#if defined(DEBUG) && !V8_OS_WIN
2116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static int file_num = 0;
2117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (FLAG_gdbjit_dump && dump_if_enabled) {
2118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    static const int kMaxFileNameSize = 64;
2119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    char file_name[64];
2120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SNPrintF(Vector<char>(file_name, kMaxFileNameSize), "/tmp/elfdump%s%d.o",
2122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             (name_hint != NULL) ? name_hint : "", file_num++);
2123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    WriteBytes(file_name, entry->symfile_addr_,
2124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch               static_cast<int>(entry->symfile_size_));
2125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
2127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CodeMap::Locator cur;
2129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK(map->Insert(range, &cur));
2130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  cur.set_value(entry);
2131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  RegisterCodeEntry(entry);
2133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
2134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void AddCode(const char* name, Code* code, SharedFunctionInfo* shared,
2137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    LineInfo* lineinfo) {
2138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_gc;
2139b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CodeMap* code_map = GetCodeMap();
2141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AddressRange range;
2142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  range.start = code->address();
2143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  range.end = code->address() + code->CodeSize();
2144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  RemoveJITCodeEntries(code_map, range);
2145b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CodeDescription code_desc(name, code, shared, lineinfo);
2147b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
21481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) {
2149b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    delete lineinfo;
2150b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return;
2151b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
2152b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
21531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AddUnwindInfo(&code_desc);
2154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = code->GetIsolate();
2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JITCodeEntry* entry = CreateELFObject(&code_desc, isolate);
2156b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2157b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  delete lineinfo;
2158b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
21593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const char* name_hint = NULL;
21603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool should_dump = false;
21613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (FLAG_gdbjit_dump) {
21623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (strlen(FLAG_gdbjit_dump_filter) == 0) {
21633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      name_hint = name;
21643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      should_dump = true;
21653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else if (name != NULL) {
21663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      name_hint = strstr(name, FLAG_gdbjit_dump_filter);
21673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      should_dump = (name_hint != NULL);
21683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
21693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
2170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AddJITCodeEntry(code_map, range, entry, should_dump, name_hint);
2171b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
2172b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2173b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
2174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid EventHandler(const v8::JitCodeEvent* event) {
2175b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (!FLAG_gdbjit) return;
2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::LockGuard<base::Mutex> lock_guard(mutex.Pointer());
2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  switch (event->type) {
2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::JitCodeEvent::CODE_ADDED: {
2179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Address addr = reinterpret_cast<Address>(event->code_start);
2180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Code* code = Code::GetCodeFromTargetAddress(addr);
2181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      LineInfo* lineinfo = GetLineInfo(addr);
2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      EmbeddedVector<char, 256> buffer;
2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      StringBuilder builder(buffer.start(), buffer.length());
2184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      builder.AddSubstring(event->name.str, static_cast<int>(event->name.len));
2185014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // It's called UnboundScript in the API but it's a SharedFunctionInfo.
2186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SharedFunctionInfo* shared =
2187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          event->script.IsEmpty() ? NULL : *Utils::OpenHandle(*event->script);
2188014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      AddCode(builder.Finalize(), code, shared, lineinfo);
2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::JitCodeEvent::CODE_MOVED:
2192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Enabling the GDB JIT interface should disable code compaction.
2193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      UNREACHABLE();
2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    case v8::JitCodeEvent::CODE_REMOVED:
2196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Do nothing.  Instead, adding code causes eviction of any entry whose
2197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // address range intersects the address range of the added code.
2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      line_info->SetPosition(static_cast<intptr_t>(event->line_info.offset),
2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             static_cast<int>(event->line_info.pos),
2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             event->line_info.position_type ==
2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                 v8::JitCodeEvent::STATEMENT_POSITION);
2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::JitCodeEvent* mutable_event = const_cast<v8::JitCodeEvent*>(event);
2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      mutable_event->user_data = new LineInfo();
2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
2214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      PutLineInfo(reinterpret_cast<Address>(event->code_start), line_info);
2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      break;
2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
2219b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif
2220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace GDBJITInterface
2221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
2222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
2223