Select the types of activity you want to include in your feed.
Implemented an __eh_frame reader & relocator to fix __eh_frame overruns when a terminating entry is missing.
This implementation will enable future DWARF register code fixups on i386
···11+/*
22+This file is part of Darling.
33+44+Copyright (C) 2013 Lubos Dolezel
55+66+Darling is free software: you can redistribute it and/or modify
77+it under the terms of the GNU General Public License as published by
88+the Free Software Foundation, either version 3 of the License, or
99+(at your option) any later version.
1010+1111+Darling is distributed in the hope that it will be useful,
1212+but WITHOUT ANY WARRANTY; without even the implied warranty of
1313+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+GNU General Public License for more details.
1515+1616+You should have received a copy of the GNU General Public License
1717+along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818+*/
1919+2020+#include "BufReader.h"
2121+#include <stdexcept>
2222+2323+BufReader::BufReader(const void* mem, uintptr_t length)
2424+{
2525+ m_pPos = m_pStart = static_cast<const char*>(mem);
2626+ m_pEnd = m_pStart + length;
2727+}
2828+2929+void BufReader::checkRead(size_t bytes) const
3030+{
3131+ if (m_pPos+bytes > m_pEnd)
3232+ throw std::runtime_error("Read beyond buffer's end");
3333+}
3434+3535+const void* BufReader::readBlock(size_t bytes)
3636+{
3737+ const char* rv = m_pPos;
3838+3939+ checkRead(bytes);
4040+ m_pPos += bytes;
4141+4242+ return rv;
4343+}
4444+4545+const char* BufReader::readString()
4646+{
4747+ const char* start = m_pPos;
4848+4949+ while (read());
5050+5151+ return start;
5252+}
5353+5454+void BufReader::unget(size_t bytes)
5555+{
5656+ if (m_pPos - bytes < m_pStart)
5757+ throw std::runtime_error("Unget beyond buffer's start");
5858+ m_pPos -= bytes;
5959+}
6060+6161+uint64_t BufReader::readULEB128()
6262+{
6363+ uint64_t r = 0;
6464+ int s = 0;
6565+ uint8_t val;
6666+6767+ do
6868+ {
6969+ val = read();
7070+ r |= (uint64_t)(val & 0x7f) << s;
7171+ s += 7;
7272+ }
7373+ while (val & 0x80);
7474+7575+ return r;
7676+}
7777+7878+int64_t BufReader::readLEB128()
7979+{
8080+ int64_t r = 0;
8181+ int s = 0;
8282+ for (;;)
8383+ {
8484+ uint8_t b = read();
8585+ if (b < 0x80)
8686+ {
8787+ if (b & 0x40)
8888+ r -= (0x80 - b) << s;
8989+ else
9090+ r |= (b & 0x3f) << s;
9191+ break;
9292+ }
9393+ r |= (b & 0x7f) << s;
9494+ s += 7;
9595+ }
9696+ return r;
9797+}
9898+9999+DwarfPointer BufReader::readDwarfPointer(uint8_t encoding)
100100+{
101101+ DwarfPointer ptr;
102102+103103+ ptr.encoding = encoding;
104104+ ptr.originalLocation = pos();
105105+106106+ switch (encoding & 0x0f)
107107+ {
108108+ case 0x01: // uleb128
109109+ ptr.udata8 = readULEB128();
110110+ break;
111111+ case 0x02: // udata2
112112+ ptr.udata2 = read16();
113113+ break;
114114+ case 0x03: // udata4
115115+ ptr.udata4 = read32();
116116+ break;
117117+ case 0x04: // udata8
118118+ ptr.udata8 = read64();
119119+ break;
120120+ case (0x01|0x08): // sleb128
121121+ ptr.sdata8 = readLEB128();
122122+ break;
123123+ case (0x02|0x08): // sdata2
124124+ ptr.sdata2 = read16S();
125125+ break;
126126+ case (0x03|0x08): // sdata4
127127+ ptr.sdata4 = read32S();
128128+ break;
129129+ case (0x04|0x08): // sdata8
130130+ ptr.sdata8 = read64S();
131131+ break;
132132+ case 0: // absptr
133133+ {
134134+ if (sizeof(void*) == 4)
135135+ ptr.udata4 = read32();
136136+ else
137137+ ptr.udata8 = read64();
138138+ }
139139+ }
140140+141141+ return ptr;
142142+}
+68
src/dyld/eh/BufReader.h
···11+/*
22+This file is part of Darling.
33+44+Copyright (C) 2013 Lubos Dolezel
55+66+Darling is free software: you can redistribute it and/or modify
77+it under the terms of the GNU General Public License as published by
88+the Free Software Foundation, either version 3 of the License, or
99+(at your option) any later version.
1010+1111+Darling is distributed in the hope that it will be useful,
1212+but WITHOUT ANY WARRANTY; without even the implied warranty of
1313+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+GNU General Public License for more details.
1515+1616+You should have received a copy of the GNU General Public License
1717+along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818+*/
1919+2020+#ifndef BUFREADER_H
2121+#define BUFREADER_H
2222+#include <stdint.h>
2323+#include <stddef.h>
2424+#include "DwarfPointer.h"
2525+2626+2727+class BufReader
2828+{
2929+public:
3030+ BufReader(const void* mem, uintptr_t length);
3131+3232+ template<typename T> T readType() { const T* t = static_cast<const T*>(readBlock(sizeof(T))); return *t; }
3333+3434+ uintptr_t readPtr() { return readType<uintptr_t>(); }
3535+ intptr_t readPtrS() { return readType<intptr_t>(); }
3636+3737+ uint16_t read16() { return readType<uint16_t>(); }
3838+ int16_t read16S() { return readType<int16_t>(); }
3939+4040+ uint32_t read32() { return readType<uint32_t>(); }
4141+ int32_t read32S() { return readType<int32_t>(); }
4242+4343+ uint64_t read64() { return readType<uint64_t>(); }
4444+ int64_t read64S() { return readType<int64_t>(); }
4545+4646+ uint8_t read() { return readType<uint8_t>(); }
4747+ int8_t readS() { return readType<int8_t>(); }
4848+4949+ uint64_t readULEB128();
5050+ int64_t readLEB128();
5151+5252+ DwarfPointer readDwarfPointer(uint8_t encoding);
5353+5454+ const void* readBlock(size_t bytes);
5555+ const char* readString();
5656+5757+ void unget(size_t bytes);
5858+5959+ bool atEnd() const { return m_pPos == m_pEnd; }
6060+ uintptr_t pos() const { return reinterpret_cast<uintptr_t>(m_pPos); }
6161+ void moveTo(uintptr_t pos) { m_pPos = reinterpret_cast<const char*>(pos); }
6262+private:
6363+ void checkRead(size_t bytes) const;
6464+private:
6565+ const char *m_pStart, *m_pPos, *m_pEnd;
6666+};
6767+6868+#endif
+125
src/dyld/eh/BufWriter.cpp
···11+/*
22+This file is part of Darling.
33+44+Copyright (C) 2013 Lubos Dolezel
55+66+Darling is free software: you can redistribute it and/or modify
77+it under the terms of the GNU General Public License as published by
88+the Free Software Foundation, either version 3 of the License, or
99+(at your option) any later version.
1010+1111+Darling is distributed in the hope that it will be useful,
1212+but WITHOUT ANY WARRANTY; without even the implied warranty of
1313+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+GNU General Public License for more details.
1515+1616+You should have received a copy of the GNU General Public License
1717+along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818+*/
1919+2020+#include "BufWriter.h"
2121+#include <stdexcept>
2222+#include <cstring>
2323+2424+BufWriter::BufWriter(void* mem, uintptr_t length)
2525+{
2626+ m_pPos = m_pStart = static_cast<char*>(mem);
2727+ m_pEnd = m_pStart + length;
2828+}
2929+3030+void BufWriter::writeULEB128(uint64_t v)
3131+{
3232+ do
3333+ {
3434+ uint8_t byte = v & 0x7f;
3535+ v >>= 7;
3636+ if (v != 0)
3737+ byte |= 0x80;
3838+ write(byte);
3939+ }
4040+ while (v != 0);
4141+}
4242+4343+void BufWriter::writeLEB128(int64_t v)
4444+{
4545+ bool more = true;
4646+ bool negative = (v < 0);
4747+4848+ int bitsUsed = 0;
4949+ for (int i = 0; i < 64; i++)
5050+ {
5151+ if (v & (1ll << i))
5252+ bitsUsed = i+1;
5353+ }
5454+5555+ while(more)
5656+ {
5757+ uint8_t byte = v & 0x7f;
5858+ v >>= 7;
5959+6060+ if (negative)
6161+ v |= - (1 <<(bitsUsed - 7));
6262+6363+ if ((v == 0 && !(byte & 0x40)) || (v == -1 && (byte & 0x40)))
6464+ more = false;
6565+ else
6666+ byte |= 0x80;
6767+ write(byte);
6868+ }
6969+}
7070+7171+void BufWriter::writeDwarfPointer(DwarfPointer ptr)
7272+{
7373+ switch (ptr.encoding & 0xf)
7474+ {
7575+ case 0x01: // uleb128
7676+ writeULEB128(ptr.udata8);
7777+ break;
7878+ case 0x02: // udata2
7979+ write16(ptr.udata2);
8080+ break;
8181+ case 0x03: // udata4
8282+ write32(ptr.udata4);
8383+ break;
8484+ case 0x04: // udata8
8585+ write64(ptr.udata8);
8686+ break;
8787+ case (0x01|0x08): // sleb128
8888+ writeLEB128(ptr.sdata8);
8989+ break;
9090+ case (0x02|0x08): // sdata2
9191+ write16S(ptr.sdata2);
9292+ break;
9393+ case (0x03|0x08): // sdata4
9494+ write32S(ptr.sdata4);
9595+ break;
9696+ case (0x04|0x08): // sdata8
9797+ write64S(ptr.sdata8);
9898+ break;
9999+ case 0: // absptr
100100+ {
101101+ if (sizeof(void*) == 4)
102102+ write32(ptr.udata4);
103103+ else
104104+ write64(ptr.udata8);
105105+ }
106106+ }
107107+}
108108+109109+void BufWriter::writeBlock(const void* p, size_t bytes)
110110+{
111111+ checkWrite(bytes);
112112+ memcpy(m_pPos, p, bytes);
113113+ m_pPos += bytes;
114114+}
115115+116116+void BufWriter::writeString(const char* str)
117117+{
118118+ writeBlock(str, strlen(str)+1);
119119+}
120120+121121+void BufWriter::checkWrite(size_t bytes) const
122122+{
123123+ if (m_pPos+bytes > m_pEnd)
124124+ throw std::runtime_error("Write beyond buffer's end");
125125+}
+67
src/dyld/eh/BufWriter.h
···11+/*
22+This file is part of Darling.
33+44+Copyright (C) 2013 Lubos Dolezel
55+66+Darling is free software: you can redistribute it and/or modify
77+it under the terms of the GNU General Public License as published by
88+the Free Software Foundation, either version 3 of the License, or
99+(at your option) any later version.
1010+1111+Darling is distributed in the hope that it will be useful,
1212+but WITHOUT ANY WARRANTY; without even the implied warranty of
1313+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+GNU General Public License for more details.
1515+1616+You should have received a copy of the GNU General Public License
1717+along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818+*/
1919+2020+#ifndef BUFWRITER_H
2121+#define BUFWRITER_H
2222+#include <stdint.h>
2323+#include <stddef.h>
2424+#include "DwarfPointer.h"
2525+2626+class BufWriter
2727+{
2828+public:
2929+ BufWriter(void* mem, uintptr_t length);
3030+3131+ template<typename T> void writeType(T t) { writeBlock(&t, sizeof(T)); }
3232+3333+ void writePtr(uintptr_t v) { return writeType<uintptr_t>(v); }
3434+ void writePtrS(intptr_t v) { return writeType<intptr_t>(v); }
3535+3636+ void write16(uint16_t v) { return writeType<uint16_t>(v); }
3737+ void write16S(int16_t v) { return writeType<int16_t>(v); }
3838+3939+ void write32(uint32_t v) { return writeType<uint32_t>(v); }
4040+ void write32S(int32_t v) { return writeType<int32_t>(v); }
4141+4242+ void write64(uint64_t v) { return writeType<uint64_t>(v); }
4343+ void write64S(int64_t v) { return writeType<int64_t>(v); }
4444+4545+ void write(uint8_t v) { return writeType<uint8_t>(v); }
4646+ void writeS(int8_t v) { return writeType<int8_t>(v); }
4747+4848+ void writeULEB128(uint64_t v);
4949+ void writeLEB128(int64_t v);
5050+5151+ void writeDwarfPointer(DwarfPointer ptr);
5252+5353+ void writeBlock(const void* p, size_t bytes);
5454+ void writeString(const char* str);
5555+5656+ bool atEnd() const { return m_pPos == m_pEnd; }
5757+ uintptr_t pos() const { return reinterpret_cast<uintptr_t>(m_pPos); }
5858+ uintptr_t relativePos() const { return m_pPos - m_pStart; }
5959+ char* posPtr() const { return m_pPos; }
6060+ void moveTo(uintptr_t pos) { m_pPos = reinterpret_cast<char*>(pos); }
6161+private:
6262+ void checkWrite(size_t bytes) const;
6363+private:
6464+ char *m_pStart, *m_pPos, *m_pEnd;
6565+};
6666+6767+#endif
+101
src/dyld/eh/DwarfPointer.cpp
···11+#include "DwarfPointer.h"
22+#include <stdexcept>
33+44+bool DwarfPointer::relocateToAddr(uintptr_t addr, uintptr_t originalBlockStart, uintptr_t originalBlockEnd)
55+{
66+ if (!(encoding & 0x10)) // DW_EH_PE_pcrel; == cannot be used because pcrel can be combined with indirect...
77+ return false;
88+99+ if (originalLocation+getSigned() >= originalBlockStart && originalLocation+getSigned() < originalBlockEnd)
1010+ return false; // nothing to change, it was inside of the EH block
1111+1212+ setSigned(getSigned() + (originalLocation - addr));
1313+ originalLocation = addr;
1414+ return true;
1515+}
1616+1717+int DwarfPointer::getSize()
1818+{
1919+ return getSize(encoding);
2020+}
2121+2222+int DwarfPointer::getSize(uint8_t encoding)
2323+{
2424+ switch (encoding & 0xf)
2525+ {
2626+ case 0x01: // uleb128
2727+ throw std::logic_error("leb128 size cannot be precalculated");
2828+ case 0x02: // udata2
2929+ return 2;
3030+ case 0x03: // udata4
3131+ return 4;
3232+ case 0x04: // udata8
3333+ return 8;
3434+ case (0x01|0x08): // sleb128
3535+ throw std::logic_error("uleb128 size cannot be precalculated");
3636+ case (0x02|0x08): // sdata2
3737+ return 2;
3838+ case (0x03|0x08): // sdata4
3939+ return 4;
4040+ case (0x04|0x08): // sdata8
4141+ return 8;
4242+ case 0: // absptr
4343+ return sizeof(void*);
4444+ }
4545+ return 0;
4646+}
4747+4848+int64_t DwarfPointer::getSigned()
4949+{
5050+ switch (encoding & 0xf)
5151+ {
5252+ case 0x01: // uleb128
5353+ return udata8;
5454+ case 0x02: // udata2
5555+ return udata2;
5656+ case 0x03: // udata4
5757+ return udata4;
5858+ case 0x04: // udata8
5959+ return udata8;
6060+ case (0x01|0x08): // sleb128
6161+ return sdata8;
6262+ case (0x02|0x08): // sdata2
6363+ return sdata2;
6464+ case (0x03|0x08): // sdata4
6565+ return sdata4;
6666+ case (0x04|0x08): // sdata8
6767+ return sdata8;
6868+ case 0: // absptr
6969+ {
7070+ if (sizeof(void*) == 4)
7171+ return udata4;
7272+ else
7373+ return udata8;
7474+ }
7575+ }
7676+ return 0; // to shut the compiler up
7777+}
7878+7979+void DwarfPointer::setSigned(intptr_t value)
8080+{
8181+ uint8_t newEncoding = encoding & 0xf0;
8282+8383+ // always use sdata4/8 to simplify calculations in EHSection
8484+ if (sizeof(void*) == 8)
8585+ {
8686+ newEncoding |= (0x04|0x08);
8787+ sdata8 = value;
8888+ }
8989+ else
9090+ {
9191+ newEncoding |= (0x03|0x08);
9292+ sdata4 = value;
9393+ }
9494+ encoding = newEncoding;
9595+}
9696+9797+void DwarfPointer::prepareForRelocation()
9898+{
9999+ if (encoding != 0xff) // DW_EH_PE_omit
100100+ setSigned(getSigned());
101101+}
+52
src/dyld/eh/DwarfPointer.h
···11+/*
22+This file is part of Darling.
33+44+Copyright (C) 2013 Lubos Dolezel
55+66+Darling is free software: you can redistribute it and/or modify
77+it under the terms of the GNU General Public License as published by
88+the Free Software Foundation, either version 3 of the License, or
99+(at your option) any later version.
1010+1111+Darling is distributed in the hope that it will be useful,
1212+but WITHOUT ANY WARRANTY; without even the implied warranty of
1313+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+GNU General Public License for more details.
1515+1616+You should have received a copy of the GNU General Public License
1717+along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818+*/
1919+2020+#ifndef DWARFPOINTER_H
2121+#define DWARFPOINTER_H
2222+#include <stdint.h>
2323+2424+struct DwarfPointer
2525+{
2626+ DwarfPointer() : encoding(0xff), sdata8(0) {}
2727+2828+ bool relocateToAddr(uintptr_t addr, uintptr_t originalBlockStart, uintptr_t originalBlockEnd);
2929+ int64_t getSigned();
3030+ void setSigned(intptr_t value);
3131+3232+ // Used to change the internal data type to what is used after relocation
3333+ // Needed when we need to write the encoding somewhere (CIE) long before writing the pointer itself (FDE)
3434+ void prepareForRelocation();
3535+ int getSize();
3636+ static int getSize(uint8_t encoding);
3737+3838+ uint8_t encoding;
3939+ union
4040+ {
4141+ uint64_t udata8;
4242+ int64_t sdata8;
4343+ uint32_t udata4;
4444+ int32_t sdata4;
4545+ uint16_t udata2;
4646+ int32_t sdata2;
4747+ };
4848+4949+ uintptr_t originalLocation;
5050+};
5151+5252+#endif
+376
src/dyld/eh/EHSection.cpp
···11+/*
22+This file is part of Darling.
33+44+Copyright (C) 2013 Lubos Dolezel
55+66+Darling is free software: you can redistribute it and/or modify
77+it under the terms of the GNU General Public License as published by
88+the Free Software Foundation, either version 3 of the License, or
99+(at your option) any later version.
1010+1111+Darling is distributed in the hope that it will be useful,
1212+but WITHOUT ANY WARRANTY; without even the implied warranty of
1313+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+GNU General Public License for more details.
1515+1616+You should have received a copy of the GNU General Public License
1717+along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818+*/
1919+2020+#include "EHSection.h"
2121+#include <string>
2222+#include <stdexcept>
2323+#include <sstream>
2424+#include <limits>
2525+#include <memory>
2626+#include <cstring>
2727+#include "../../util/log.h"
2828+2929+EHSection::EHSection()
3030+{
3131+}
3232+3333+EHSection::~EHSection()
3434+{
3535+ clear();
3636+}
3737+3838+void EHSection::clear()
3939+{
4040+ for (CIE* cie : m_cies)
4141+ {
4242+ for (FDE* fde : cie->fdes)
4343+ delete fde;
4444+ delete cie;
4545+ }
4646+ m_cies.clear();
4747+ m_ciePositions.clear();
4848+}
4949+5050+5151+void EHSection::load(const void* start, uintptr_t length)
5252+{
5353+ BufReader reader(start, length);
5454+5555+ clear();
5656+5757+ m_originalStart = reinterpret_cast<uintptr_t>(start);
5858+ m_originalEnd = m_originalStart + length;
5959+6060+ while (!reader.atEnd())
6161+ {
6262+ uint64_t length;
6363+ int32_t id;
6464+ uintptr_t location, endPos;
6565+6666+ location = reader.pos();
6767+6868+ length = uint64_t(reader.read32()) & 0xffffffff;
6969+7070+ if (length == 0xffffffff)
7171+ length = reader.read64();
7272+ else if (!length)
7373+ break; // terminating entry
7474+7575+ endPos = reader.pos() + length;
7676+ id = reader.read32S();
7777+7878+ if (!id)
7979+ loadCIE(reader, endPos, location);
8080+ else
8181+ {
8282+ uintptr_t pos = reader.pos() - sizeof(id); // offset is from the id field
8383+ pos -= id;
8484+8585+ auto it = m_ciePositions.find(pos);
8686+ if (it == m_ciePositions.end())
8787+ {
8888+ std::stringstream ss;
8989+ ss << "CIE not found for position " << std::hex << pos << std::dec << std::endl;
9090+ throw std::runtime_error(ss.str());
9191+ }
9292+9393+ loadFDE(reader, endPos, it->second);
9494+ }
9595+ }
9696+}
9797+9898+void EHSection::loadCIE(BufReader& reader, uint64_t endPos, uintptr_t location)
9999+{
100100+ CIE* cie = new CIE;
101101+102102+ cie->start = reader.pos();
103103+ cie->version = reader.read();
104104+ cie->augmentationString = reader.readString();
105105+ cie->codeAlign = reader.readLEB128();
106106+ cie->dataAlign = reader.readLEB128();
107107+108108+ if (cie->codeAlign != 1)
109109+ {
110110+ std::stringstream ss;
111111+ ss << "Invalid code alignment: " << int(cie->codeAlign) << std::endl;
112112+ delete cie;
113113+ throw std::runtime_error(ss.str());
114114+ }
115115+116116+ if (cie->version == 1)
117117+ cie->returnRegister = reader.read();
118118+ else if (cie->version == 3)
119119+ cie->returnRegister = reader.readLEB128();
120120+ else
121121+ {
122122+ std::stringstream ss;
123123+ ss << "Invalid CIE version: " << int(cie->version) << std::endl;
124124+ delete cie;
125125+ throw std::runtime_error(ss.str());
126126+ }
127127+128128+ cie->augmentationDataPresent = false;
129129+130130+ uint64_t augmentationDataLength, augmentationDataEnd;
131131+132132+ cie->lsdaEncoding = cie->ptrEncoding = 0xff;
133133+134134+ for (const char* augP = cie->augmentationString; *augP; augP++)
135135+ {
136136+ switch (*augP)
137137+ {
138138+ case 'z':
139139+ cie->augmentationDataPresent = true;
140140+ augmentationDataLength = reader.readULEB128();
141141+ augmentationDataEnd = reader.pos() + augmentationDataLength;
142142+ break;
143143+ case 'L':
144144+ cie->lsdaEncoding = reader.read();
145145+ break;
146146+ case 'R':
147147+ cie->ptrEncoding = reader.read();
148148+ break;
149149+ case 'P':
150150+ {
151151+ uint8_t persEncoding = reader.read();
152152+ cie->personality = reader.readDwarfPointer(persEncoding);
153153+ break;
154154+ }
155155+ case 'S':
156156+ break;
157157+ default:
158158+ {
159159+ std::stringstream ss;
160160+ ss << "Unsupported character in CIE augmentation string: " << *augP;
161161+ delete cie;
162162+163163+ throw std::runtime_error(ss.str());
164164+ }
165165+ }
166166+ }
167167+168168+ reader.moveTo(augmentationDataEnd);
169169+170170+ uint64_t instructionsLength = endPos - reader.pos();
171171+ const uint8_t* data = reinterpret_cast<const uint8_t*>(reader.readBlock(instructionsLength));
172172+173173+ cie->instructions.assign(data, data+instructionsLength);
174174+175175+ m_cies.push_back(cie);
176176+ m_ciePositions[location] = cie;
177177+178178+ LOG << "Loaded a CIE at " << std::hex << location << std::dec << std::endl;
179179+}
180180+181181+void EHSection::loadFDE(BufReader& reader, uint64_t endPos, CIE* cie)
182182+{
183183+ FDE* fde = new FDE;
184184+185185+ fde->startAddress = reader.readDwarfPointer(cie->ptrEncoding);
186186+ fde->length = reader.readDwarfPointer(cie->ptrEncoding); // if ptrEncoding is relative, then in context of length, it is still just a plain number
187187+188188+ if (*cie->augmentationString == 'z')
189189+ {
190190+ fde->augmentationDataLength = reader.readLEB128();
191191+ //fde->augmentationData = reinterpret_cast<const uint8_t*>(reader.readBlock(fde->augmentationDataLength));
192192+ }
193193+ else
194194+ {
195195+ fde->augmentationDataLength = 0;
196196+ //fde->augmentationData = nullptr;
197197+ }
198198+199199+ if (strchr(cie->augmentationString, 'L') && cie->lsdaEncoding != 0xff) // DW_EH_PE_omit
200200+ fde->lsdaPointer = reader.readDwarfPointer(cie->lsdaEncoding);
201201+202202+ uint64_t instructionsLength = endPos - reader.pos();
203203+ const uint8_t* data = reinterpret_cast<const uint8_t*>(reader.readBlock(instructionsLength));
204204+205205+ fde->instructions.assign(data, data+instructionsLength);
206206+207207+ cie->fdes.push_back(fde);
208208+}
209209+210210+void EHSection::store(void** mem, uintptr_t* length)
211211+{
212212+ uintptr_t originalLength = m_originalEnd - m_originalStart;
213213+ uintptr_t newLength;
214214+215215+ // We're being pessimistic here, but we cannot use a resizable buffer,
216216+ // since a possible move doing realloc() would invalidate the relative pointers
217217+ newLength = originalLength * 2;
218218+219219+ *mem = new char[newLength];
220220+221221+ BufWriter writer (*mem, newLength);
222222+223223+ for (CIE* cie : m_cies)
224224+ {
225225+ uintptr_t cieStart = writer.pos();
226226+ // Write the CIE
227227+ storeCIE(writer, cie);
228228+229229+ // Write all the FDEs contained
230230+ for (FDE* fde : cie->fdes)
231231+ storeFDE(writer, fde, cie, cieStart);
232232+ }
233233+234234+ // terminating entry
235235+ writer.write32(0);
236236+237237+ *length = writer.pos() - reinterpret_cast<uintptr_t>(*mem);
238238+}
239239+240240+void EHSection::storeCIE(BufWriter& writer, CIE* cie)
241241+{
242242+ uint32_t* totalLength32 = nullptr;
243243+ uint64_t* totalLength64 = nullptr;
244244+245245+ if (cie->instructions.size() < std::numeric_limits<uint32_t>::max() - 100) // approximation
246246+ {
247247+ totalLength32 = reinterpret_cast<uint32_t*>(writer.posPtr());
248248+ writer.write32(0); // we fill this up later
249249+ }
250250+ else
251251+ {
252252+ writer.write32(0xffffffff);
253253+ totalLength64 = reinterpret_cast<uint64_t*>(writer.posPtr());
254254+ writer.write64(0); // we fill this up later
255255+ }
256256+257257+ uintptr_t startPos = writer.pos();
258258+259259+ writer.write32(0); // id is always zero for a CIE
260260+261261+ writer.write(cie->version);
262262+ writer.writeString(cie->augmentationString);
263263+ writer.writeLEB128(cie->codeAlign);
264264+ writer.writeLEB128(cie->dataAlign);
265265+266266+ if (cie->version == 1)
267267+ writer.write(cie->returnRegister & 0xff);
268268+ else if (cie->version == 3)
269269+ writer.writeLEB128(cie->returnRegister);
270270+ else
271271+ throw std::runtime_error("Invalid CIE version");
272272+273273+ // TODO: cie->lsdaEncodingPtr
274274+ // augmentation data length will always be
275275+ // 1 + 1 + 1 + 4|8
276276+277277+ uint64_t augLength = 0;
278278+ if (strchr(cie->augmentationString, 'L'))
279279+ augLength++;
280280+ if (strchr(cie->augmentationString, 'R'))
281281+ augLength++;
282282+ if (strchr(cie->augmentationString, 'P'))
283283+ augLength += sizeof(void*) + 1; // sizeof(void*), because relocateToAddr() forces this
284284+285285+ writer.writeULEB128(augLength);
286286+287287+ for (const char* augP = cie->augmentationString; *augP; augP++)
288288+ {
289289+ switch (*augP)
290290+ {
291291+ case 'z':
292292+ break;
293293+ case 'L':
294294+295295+ writer.write(cie->lsdaEncoding);
296296+ break;
297297+ case 'R':
298298+ writer.write(cie->ptrEncoding);
299299+ break;
300300+ case 'P':
301301+ {
302302+ cie->personality.relocateToAddr(writer.pos()+1, m_originalStart, m_originalEnd); // not relocated?!
303303+ writer.write(cie->personality.encoding);
304304+ writer.writeDwarfPointer(cie->personality);
305305+ break;
306306+ }
307307+ case 'S':
308308+ break;
309309+ default:
310310+ {
311311+ std::stringstream ss;
312312+ ss << "Unsupported character in CIE augmentation string: " << *augP;
313313+ delete cie;
314314+315315+ throw std::runtime_error(ss.str());
316316+ }
317317+ }
318318+ }
319319+320320+ writer.writeBlock(&cie->instructions[0], cie->instructions.size());
321321+322322+ if (totalLength32)
323323+ *totalLength32 = uint32_t( writer.pos() - startPos );
324324+ else
325325+ *totalLength64 = writer.pos() - startPos;
326326+}
327327+328328+void EHSection::storeFDE(BufWriter& writer, FDE* fde, CIE* cie, uintptr_t cieStart)
329329+{
330330+ uint32_t* totalLength32 = nullptr;
331331+ uint64_t* totalLength64 = nullptr;
332332+333333+ if (fde->instructions.size() < std::numeric_limits<uint32_t>::max() - 100) // approximation
334334+ {
335335+ totalLength32 = reinterpret_cast<uint32_t*>(writer.posPtr());
336336+ writer.write32(0); // we fill this up later
337337+ }
338338+ else
339339+ {
340340+ writer.write32(0xffffffff);
341341+ totalLength64 = reinterpret_cast<uint64_t*>(writer.posPtr());
342342+ writer.write64(0); // we fill this up later
343343+ }
344344+345345+ uintptr_t startPos = writer.pos();
346346+ int32_t id = int32_t(writer.pos() - cieStart);
347347+ writer.write32S(id);
348348+349349+ fde->startAddress.relocateToAddr(writer.pos(), m_originalStart, m_originalEnd);
350350+ writer.writeDwarfPointer(fde->startAddress);
351351+ writer.writeDwarfPointer(fde->length); // length cannot be relative
352352+353353+ if (*cie->augmentationString == 'z')
354354+ {
355355+ bool hasLSDAPtr = (strchr(cie->augmentationString, 'L') && cie->lsdaEncoding != 0xff); // DW_EH_PE_omit
356356+357357+ writer.writeLEB128(hasLSDAPtr ? DwarfPointer::getSize(cie->lsdaEncoding) : 0);
358358+359359+ if (hasLSDAPtr)
360360+ {
361361+ fde->lsdaPointer.relocateToAddr(writer.pos(), m_originalStart, m_originalEnd);
362362+ writer.writeDwarfPointer(fde->lsdaPointer);
363363+ }
364364+ }
365365+366366+ writer.writeBlock(&fde->instructions[0], fde->instructions.size());
367367+368368+ if (totalLength32)
369369+ *totalLength32 = uint32_t( writer.pos() - startPos );
370370+ else
371371+ *totalLength64 = writer.pos() - startPos;
372372+}
373373+374374+void EHSection::swapRegisterNumbers(const std::vector<std::pair<int, int>>& swapList)
375375+{
376376+}
+97
src/dyld/eh/EHSection.h
···11+/*
22+This file is part of Darling.
33+44+Copyright (C) 2013 Lubos Dolezel
55+66+Darling is free software: you can redistribute it and/or modify
77+it under the terms of the GNU General Public License as published by
88+the Free Software Foundation, either version 3 of the License, or
99+(at your option) any later version.
1010+1111+Darling is distributed in the hope that it will be useful,
1212+but WITHOUT ANY WARRANTY; without even the implied warranty of
1313+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+GNU General Public License for more details.
1515+1616+You should have received a copy of the GNU General Public License
1717+along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818+*/
1919+2020+#ifndef EHSECTION_H
2121+#define EHSECTION_H
2222+#include <stdint.h>
2323+#include <vector>
2424+#include <map>
2525+#include "BufReader.h"
2626+#include "BufWriter.h"
2727+2828+class EHSection
2929+{
3030+public:
3131+ EHSection();
3232+ ~EHSection();
3333+3434+ // Loads an __eh_frame
3535+ void load(const void* start, uintptr_t length);
3636+3737+ // Serializes a previously loaded __eh_frame, appends a terminating entry
3838+ // The returned memory must not be moved
3939+ void store(void** mem, uintptr_t* length);
4040+4141+ // Frees all the internal structures
4242+ void clear();
4343+4444+ void swapRegisterNumbers(const std::vector<std::pair<int, int>>& swapList);
4545+private:
4646+ struct CIE;
4747+ struct FDE;
4848+4949+ // Loads a CIE from the given reader
5050+ // endPos: absolute address of the first byte after this CIE, used to get the instruction block length
5151+ // location: absolute address of the length field preceding this CIE
5252+ void loadCIE(BufReader& reader, uint64_t endPos, uintptr_t location);
5353+5454+ // Loads an FDE from the given reader
5555+ // endPos: absolute address of the first byte after this FDE, used to get the instruction block length
5656+ // cie: a CIE this FDE is part of, determined by the location passed in loadCIE() matched by the 'id'
5757+ void loadFDE(BufReader& reader, uint64_t endPos, CIE* cie);
5858+5959+ void storeCIE(BufWriter& writer, CIE* cie);
6060+ void storeFDE(BufWriter& writer, FDE* fde, CIE* cie, uintptr_t cieStart);
6161+private:
6262+ // Needed for relative pointer adjustments
6363+ uintptr_t m_originalStart, m_originalEnd;
6464+6565+ struct FDE
6666+ {
6767+ DwarfPointer startAddress, length;
6868+ const uint8_t* augmentationData;
6969+ int64_t augmentationDataLength;
7070+ DwarfPointer lsdaPointer;
7171+7272+ std::vector<uint8_t> instructions;
7373+ };
7474+7575+ struct CIE
7676+ {
7777+ uintptr_t start;
7878+ uint8_t version;
7979+ const char* augmentationString;
8080+ int64_t codeAlign, dataAlign;
8181+ int64_t returnRegister;
8282+ bool augmentationDataPresent;
8383+ uint8_t lsdaEncoding, ptrEncoding;
8484+ DwarfPointer personality;
8585+8686+ std::vector<uint8_t> instructions;
8787+ std::vector<FDE*> fdes;
8888+ uint8_t* lsdaEncodingPtr; // only used when writing
8989+ };
9090+9191+ std::vector<CIE*> m_cies;
9292+9393+ // Used to look up the CIE an FDE belongs into
9494+ std::map<uintptr_t, CIE*> m_ciePositions;
9595+};
9696+9797+#endif