17a7112b3SIngo Weinhold/*
27483c98dSIngo Weinhold * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
37cab8329SRene Gollent * Copyright 2012-2014, Rene Gollent, rene@gollent.com.
47a7112b3SIngo Weinhold * Distributed under the terms of the MIT License.
57a7112b3SIngo Weinhold */
67a7112b3SIngo Weinhold
7f7526300SIngo Weinhold
87a7112b3SIngo Weinhold#include "DwarfFile.h"
97a7112b3SIngo Weinhold
10593fa677SIngo Weinhold#include <algorithm>
117a7112b3SIngo Weinhold#include <new>
127a7112b3SIngo Weinhold
137a7112b3SIngo Weinhold#include <AutoDeleter.h>
14224f7510SRene Gollent#include <Entry.h>
15224f7510SRene Gollent#include <FindDirectory.h>
16224f7510SRene Gollent#include <Path.h>
17acaa4271SRene Gollent#include <PathFinder.h>
187a7112b3SIngo Weinhold
197a7112b3SIngo Weinhold#include "AttributeClasses.h"
207a7112b3SIngo Weinhold#include "AttributeValue.h"
217a7112b3SIngo Weinhold#include "AbbreviationTable.h"
22f7526300SIngo Weinhold#include "CfaContext.h"
237a7112b3SIngo Weinhold#include "CompilationUnit.h"
247a7112b3SIngo Weinhold#include "DataReader.h"
25d315bfd5SIngo Weinhold#include "DwarfExpressionEvaluator.h"
26f7526300SIngo Weinhold#include "DwarfTargetInterface.h"
277a7112b3SIngo Weinhold#include "ElfFile.h"
287a7112b3SIngo Weinhold#include "TagNames.h"
295b60969cSIngo Weinhold#include "TargetAddressRangeList.h"
306e72ebfcSIngo Weinhold#include "Tracing.h"
31d315bfd5SIngo Weinhold#include "Variant.h"
327a7112b3SIngo Weinhold
337a7112b3SIngo Weinhold
34224f7510SRene Gollent// #pragma mark - AutoSectionPutter
35224f7510SRene Gollent
36224f7510SRene Gollent
37224f7510SRene Gollentclass AutoSectionPutter {
38224f7510SRene Gollentpublic:
39224f7510SRene Gollent	AutoSectionPutter(ElfFile* elfFile, ElfSection* elfSection)
40224f7510SRene Gollent		:
41224f7510SRene Gollent		fElfFile(elfFile),
42224f7510SRene Gollent		fElfSection(elfSection)
43224f7510SRene Gollent	{
44224f7510SRene Gollent	}
45224f7510SRene Gollent
46224f7510SRene Gollent	~AutoSectionPutter()
47224f7510SRene Gollent	{
48224f7510SRene Gollent		if (fElfSection != NULL)
49224f7510SRene Gollent			fElfFile->PutSection(fElfSection);
50224f7510SRene Gollent	}
51224f7510SRene Gollent
52224f7510SRene Gollentprivate:
53224f7510SRene Gollent	ElfFile*			fElfFile;
54224f7510SRene Gollent	ElfSection*			fElfSection;
55224f7510SRene Gollent};
56224f7510SRene Gollent
57224f7510SRene Gollent
58b312b9ffSIngo Weinhold// #pragma mark - ExpressionEvaluationContext
59b312b9ffSIngo Weinhold
60b312b9ffSIngo Weinhold
61b312b9ffSIngo Weinholdstruct DwarfFile::ExpressionEvaluationContext
62b312b9ffSIngo Weinhold	: DwarfExpressionEvaluationContext {
63b312b9ffSIngo Weinholdpublic:
64b312b9ffSIngo Weinhold	ExpressionEvaluationContext(DwarfFile* file, CompilationUnit* unit,
6516b8573bSRene Gollent		uint8 addressSize, DIESubprogram* subprogramEntry,
66b312b9ffSIngo Weinhold		const DwarfTargetInterface* targetInterface,
67b312b9ffSIngo Weinhold		target_addr_t instructionPointer, target_addr_t objectPointer,
680573015dSRene Gollent		bool hasObjectPointer, target_addr_t framePointer,
691a5bb78dSRene Gollent		target_addr_t relocationDelta)
70b312b9ffSIngo Weinhold		:
7116b8573bSRene Gollent		DwarfExpressionEvaluationContext(targetInterface, addressSize,
721a5bb78dSRene Gollent			relocationDelta),
73b312b9ffSIngo Weinhold		fFile(file),
74b312b9ffSIngo Weinhold		fUnit(unit),
75b312b9ffSIngo Weinhold		fSubprogramEntry(subprogramEntry),
76b312b9ffSIngo Weinhold		fInstructionPointer(instructionPointer),
77b312b9ffSIngo Weinhold		fObjectPointer(objectPointer),
780573015dSRene Gollent		fHasObjectPointer(hasObjectPointer),
79b312b9ffSIngo Weinhold		fFramePointer(framePointer),
80b312b9ffSIngo Weinhold		fFrameBasePointer(0),
81b312b9ffSIngo Weinhold		fFrameBaseEvaluated(false)
82b312b9ffSIngo Weinhold	{
83b312b9ffSIngo Weinhold	}
84b312b9ffSIngo Weinhold
85b312b9ffSIngo Weinhold	virtual bool GetObjectAddress(target_addr_t& _address)
86b312b9ffSIngo Weinhold	{
870573015dSRene Gollent		if (!fHasObjectPointer)
88b312b9ffSIngo Weinhold			return false;
89b312b9ffSIngo Weinhold
90b312b9ffSIngo Weinhold		_address = fObjectPointer;
91b312b9ffSIngo Weinhold		return true;
92b312b9ffSIngo Weinhold	}
93b312b9ffSIngo Weinhold
94b312b9ffSIngo Weinhold	virtual bool GetFrameAddress(target_addr_t& _address)
95b312b9ffSIngo Weinhold	{
9671f75cdcSIngo Weinhold		if (fFramePointer == 0)
9771f75cdcSIngo Weinhold			return false;
9871f75cdcSIngo Weinhold
99b312b9ffSIngo Weinhold		_address = fFramePointer;
100b312b9ffSIngo Weinhold		return true;
101b312b9ffSIngo Weinhold	}
102b312b9ffSIngo Weinhold
103b312b9ffSIngo Weinhold	virtual bool GetFrameBaseAddress(target_addr_t& _address)
104b312b9ffSIngo Weinhold	{
105b312b9ffSIngo Weinhold		if (fFrameBaseEvaluated) {
106b312b9ffSIngo Weinhold			if (fFrameBasePointer == 0)
107b312b9ffSIngo Weinhold				return false;
108b312b9ffSIngo Weinhold
109b312b9ffSIngo Weinhold			_address = fFrameBasePointer;
110b312b9ffSIngo Weinhold			return true;
111b312b9ffSIngo Weinhold		}
112b312b9ffSIngo Weinhold
113b312b9ffSIngo Weinhold		// set flag already to prevent recursion for a buggy expression
114b312b9ffSIngo Weinhold		fFrameBaseEvaluated = true;
115b312b9ffSIngo Weinhold
116b312b9ffSIngo Weinhold		// get the subprogram's frame base location
11771f75cdcSIngo Weinhold		if (fSubprogramEntry == NULL)
11871f75cdcSIngo Weinhold			return false;
119b312b9ffSIngo Weinhold		const LocationDescription* location = fSubprogramEntry->FrameBase();
120b312b9ffSIngo Weinhold		if (!location->IsValid())
12185363120SIngo Weinhold			return false;
122b312b9ffSIngo Weinhold
123b312b9ffSIngo Weinhold		// get the expression
124b312b9ffSIngo Weinhold		const void* expression;
125b312b9ffSIngo Weinhold		off_t expressionLength;
126b312b9ffSIngo Weinhold		status_t error = fFile->_GetLocationExpression(fUnit, location,
127b312b9ffSIngo Weinhold			fInstructionPointer, expression, expressionLength);
128b312b9ffSIngo Weinhold		if (error != B_OK)
12985363120SIngo Weinhold			return false;
130b312b9ffSIngo Weinhold
131b312b9ffSIngo Weinhold		// evaluate the expression
132b312b9ffSIngo Weinhold		DwarfExpressionEvaluator evaluator(this);
133b312b9ffSIngo Weinhold		error = evaluator.Evaluate(expression, expressionLength,
134b312b9ffSIngo Weinhold			fFrameBasePointer);
135b312b9ffSIngo Weinhold		if (error != B_OK)
136b312b9ffSIngo Weinhold			return false;
1376e72ebfcSIngo Weinhold
1387483c98dSIngo Weinhold		TRACE_EXPR("  -> frame base: %" B_PRIx64 "\n", fFrameBasePointer);
1396e72ebfcSIngo Weinhold
140b312b9ffSIngo Weinhold		_address = fFrameBasePointer;
141b312b9ffSIngo Weinhold		return true;
142b312b9ffSIngo Weinhold	}
143b312b9ffSIngo Weinhold
144b312b9ffSIngo Weinhold	virtual bool GetTLSAddress(target_addr_t localAddress,
145b312b9ffSIngo Weinhold		target_addr_t& _address)
146b312b9ffSIngo Weinhold	{
147b312b9ffSIngo Weinhold		// TODO:...
148b312b9ffSIngo Weinhold		return false;
149b312b9ffSIngo Weinhold	}
150b312b9ffSIngo Weinhold
15171fec49eSRene Gollent	virtual status_t GetCallTarget(uint64 offset, uint8 refType,
152b312b9ffSIngo Weinhold		const void*& _block, off_t& _size)
153b312b9ffSIngo Weinhold	{
154b312b9ffSIngo Weinhold		// resolve the entry
15571fec49eSRene Gollent		DebugInfoEntry* entry = fFile->_ResolveReference(fUnit, offset, refType);
156b312b9ffSIngo Weinhold		if (entry == NULL)
157b312b9ffSIngo Weinhold			return B_ENTRY_NOT_FOUND;
158b312b9ffSIngo Weinhold
159b312b9ffSIngo Weinhold		// get the location description
160b312b9ffSIngo Weinhold		LocationDescription* location = entry->GetLocationDescription();
161b312b9ffSIngo Weinhold		if (location == NULL || !location->IsValid()) {
162b312b9ffSIngo Weinhold			_block = NULL;
163b312b9ffSIngo Weinhold			_size = 0;
164b312b9ffSIngo Weinhold			return B_OK;
165b312b9ffSIngo Weinhold		}
166b312b9ffSIngo Weinhold
167b312b9ffSIngo Weinhold		// get the expression
168b312b9ffSIngo Weinhold		return fFile->_GetLocationExpression(fUnit, location,
169b312b9ffSIngo Weinhold			fInstructionPointer, _block, _size);
170b312b9ffSIngo Weinhold	}
171b312b9ffSIngo Weinhold
172b312b9ffSIngo Weinholdprivate:
173b312b9ffSIngo Weinhold	DwarfFile*			fFile;
174b312b9ffSIngo Weinhold	CompilationUnit*	fUnit;
175b312b9ffSIngo Weinhold	DIESubprogram*		fSubprogramEntry;
176b312b9ffSIngo Weinhold	target_addr_t		fInstructionPointer;
177b312b9ffSIngo Weinhold	target_addr_t		fObjectPointer;
1780573015dSRene Gollent	bool				fHasObjectPointer;
179b312b9ffSIngo Weinhold	target_addr_t		fFramePointer;
180b312b9ffSIngo Weinhold	target_addr_t		fFrameBasePointer;
181b312b9ffSIngo Weinhold	bool				fFrameBaseEvaluated;
182b312b9ffSIngo Weinhold};
183b312b9ffSIngo Weinhold
184b312b9ffSIngo Weinhold
185be649db0SIngo Weinhold// #pragma mark - FDEAugmentation
186be649db0SIngo Weinhold
187be649db0SIngo Weinhold
188be649db0SIngo Weinholdstruct DwarfFile::FDEAugmentation {
189be649db0SIngo Weinhold	// Currently we're ignoring all augmentation data.
190be649db0SIngo Weinhold};
191be649db0SIngo Weinhold
192be649db0SIngo Weinhold
193be649db0SIngo Weinhold// #pragma mark - CIEAugmentation
194be649db0SIngo Weinhold
195be649db0SIngo Weinhold
196be649db0SIngo Weinholdenum {
197be649db0SIngo Weinhold	CFI_AUGMENTATION_DATA					= 0x01,
198be649db0SIngo Weinhold	CFI_AUGMENTATION_LANGUAGE_SPECIFIC_DATA	= 0x02,
199be649db0SIngo Weinhold	CFI_AUGMENTATION_PERSONALITY			= 0x04,
200be649db0SIngo Weinhold	CFI_AUGMENTATION_ADDRESS_POINTER_FORMAT	= 0x08,
201be649db0SIngo Weinhold};
202be649db0SIngo Weinhold
203be649db0SIngo Weinhold
204b5105244SRene Gollent// encodings for CFI_AUGMENTATION_ADDRESS_POINTER_FORMAT
205b5105244SRene Gollentenum {
206b5105244SRene Gollent	CFI_ADDRESS_FORMAT_ABSOLUTE			= 0x00,
207b5105244SRene Gollent	CFI_ADDRESS_FORMAT_UNSIGNED_LEB128	= 0x01,
208b5105244SRene Gollent	CFI_ADDRESS_FORMAT_UNSIGNED_16		= 0x02,
209b5105244SRene Gollent	CFI_ADDRESS_FORMAT_UNSIGNED_32		= 0x03,
210b5105244SRene Gollent	CFI_ADDRESS_FORMAT_UNSIGNED_64		= 0x04,
211b5105244SRene Gollent	CFI_ADDRESS_FORMAT_SIGNED			= 0x08,
212b5105244SRene Gollent	CFI_ADDRESS_FORMAT_SIGNED_LEB128	=
213b5105244SRene Gollent		CFI_ADDRESS_FORMAT_UNSIGNED_LEB128 | CFI_ADDRESS_FORMAT_SIGNED,
214b5105244SRene Gollent	CFI_ADDRESS_FORMAT_SIGNED_16		=
215b5105244SRene Gollent		CFI_ADDRESS_FORMAT_UNSIGNED_16 | CFI_ADDRESS_FORMAT_SIGNED,
216b5105244SRene Gollent	CFI_ADDRESS_FORMAT_SIGNED_32		=
217b5105244SRene Gollent		CFI_ADDRESS_FORMAT_UNSIGNED_32 | CFI_ADDRESS_FORMAT_SIGNED,
218b5105244SRene Gollent	CFI_ADDRESS_FORMAT_SIGNED_64		=
219b5105244SRene Gollent		CFI_ADDRESS_FORMAT_UNSIGNED_64 | CFI_ADDRESS_FORMAT_SIGNED
220b5105244SRene Gollent};
221b5105244SRene Gollent
222b5105244SRene Gollent
223b5105244SRene Gollentenum {
224b5105244SRene Gollent	CFI_ADDRESS_TYPE_PC_RELATIVE		= 0x10,
225b5105244SRene Gollent	CFI_ADDRESS_TYPE_TEXT_RELATIVE		= 0x20,
226b5105244SRene Gollent	CFI_ADDRESS_TYPE_DATA_RELATIVE		= 0x30,
227b5105244SRene Gollent	CFI_ADDRESS_TYPE_FUNCTION_RELATIVE	= 0x40,
228b5105244SRene Gollent	CFI_ADDRESS_TYPE_ALIGNED			= 0x50,
229b5105244SRene Gollent	CFI_ADDRESS_TYPE_INDIRECT			= 0x80
230b5105244SRene Gollent};
231b5105244SRene Gollent
232b5105244SRene Gollent
233be649db0SIngo Weinholdstruct DwarfFile::CIEAugmentation {
234be649db0SIngo Weinhold	CIEAugmentation()
235be649db0SIngo Weinhold		:
236be649db0SIngo Weinhold		fString(NULL),
237b5105244SRene Gollent		fFlags(0),
238b83bece1SRene Gollent		fAddressEncoding(CFI_ADDRESS_FORMAT_ABSOLUTE)
239be649db0SIngo Weinhold	{
240b83bece1SRene Gollent		// we default to absolute address format since that corresponds
241b83bece1SRene Gollent		// to the DWARF standard for .debug_frame. In gcc's case, however,
242b83bece1SRene Gollent		// .eh_frame will generally override that via augmentation 'R'
243be649db0SIngo Weinhold	}
244be649db0SIngo Weinhold
245be649db0SIngo Weinhold	void Init(DataReader& dataReader)
246be649db0SIngo Weinhold	{
247be649db0SIngo Weinhold		fFlags = 0;
248be649db0SIngo Weinhold		fString = dataReader.ReadString();
249be649db0SIngo Weinhold	}
250be649db0SIngo Weinhold
251be649db0SIngo Weinhold	status_t Read(DataReader& dataReader)
252be649db0SIngo Weinhold	{
253be649db0SIngo Weinhold		if (fString == NULL || *fString == '\0')
254be649db0SIngo Weinhold			return B_OK;
255be649db0SIngo Weinhold
256be649db0SIngo Weinhold		if (*fString == 'z') {
257be649db0SIngo Weinhold			// There are augmentation data.
258be649db0SIngo Weinhold			fFlags |= CFI_AUGMENTATION_DATA;
259be649db0SIngo Weinhold			const char* string = fString + 1;
260be649db0SIngo Weinhold
26116b8573bSRene Gollent			// read the augmentation data block -- it is preceeded by an
26216b8573bSRene Gollent			// LEB128 indicating the length of the data block
263b5105244SRene Gollent			uint64 length = dataReader.ReadUnsignedLEB128(0);
264b5105244SRene Gollent			uint64 remaining = length;
265be649db0SIngo Weinhold			// let's see what data we have to expect
26616b8573bSRene Gollent
26716b8573bSRene Gollent			TRACE_CFI("    %" B_PRIu64 " bytes of augmentation data\n", length);
268be649db0SIngo Weinhold			while (*string != '\0') {
269be649db0SIngo Weinhold				switch (*string) {
270be649db0SIngo Weinhold					case 'L':
271be649db0SIngo Weinhold						fFlags |= CFI_AUGMENTATION_LANGUAGE_SPECIFIC_DATA;
272b5105244SRene Gollent						dataReader.Read<char>(0);
273b5105244SRene Gollent						--remaining;
274be649db0SIngo Weinhold						break;
275be649db0SIngo Weinhold					case 'P':
27616b8573bSRene Gollent					{
277b83bece1SRene Gollent						char tempEncoding = fAddressEncoding;
278b83bece1SRene Gollent						fAddressEncoding = dataReader.Read<char>(0);
279b83bece1SRene Gollent						off_t offset = dataReader.Offset();
280b83bece1SRene Gollent						ReadEncodedAddress(dataReader, NULL, NULL, true);
281b83bece1SRene Gollent						fAddressEncoding = tempEncoding;
282b83bece1SRene Gollent						remaining -= dataReader.Offset() - offset + 1;
28316b8573bSRene Gollent 						break;
28416b8573bSRene Gollent					}
285be649db0SIngo Weinhold					case 'R':
286be649db0SIngo Weinhold						fFlags |= CFI_AUGMENTATION_ADDRESS_POINTER_FORMAT;
287b5105244SRene Gollent						fAddressEncoding = dataReader.Read<char>(0);
288b5105244SRene Gollent						--remaining;
289be649db0SIngo Weinhold						break;
290be649db0SIngo Weinhold					default:
291855f2c88SRene Gollent						WARNING("Encountered unsupported augmentation '%c' "
292855f2c88SRene Gollent							" while parsing CIE augmentation string %s\n",
293855f2c88SRene Gollent							*string, fString);
294be649db0SIngo Weinhold						return B_UNSUPPORTED;
295be649db0SIngo Weinhold				}
296be649db0SIngo Weinhold				string++;
297be649db0SIngo Weinhold			}
298be649db0SIngo Weinhold
299855f2c88SRene Gollent			// we should have read through all of the augmentation data
300855f2c88SRene Gollent			// at this point, if not, something is wrong.
30116b8573bSRene Gollent			if (remaining != 0 || dataReader.HasOverflow()) {
302855f2c88SRene Gollent				WARNING("Error while reading CIE Augmentation, expected "
303855f2c88SRene Gollent					"%" B_PRIu64 " bytes of augmentation data, but read "
304855f2c88SRene Gollent					"%" B_PRIu64 " bytes.\n", length, length - remaining);
305be649db0SIngo Weinhold				return B_BAD_DATA;
30616b8573bSRene Gollent			}
307be649db0SIngo Weinhold
308be649db0SIngo Weinhold			return B_OK;
309be649db0SIngo Weinhold		}
310be649db0SIngo Weinhold
3114ee20b83SRene Gollent		// nothing to do
3124ee20b83SRene Gollent		if (strcmp(fString, "eh") == 0)
313be649db0SIngo Weinhold			return B_OK;
314be649db0SIngo Weinhold
315be649db0SIngo Weinhold		// something we can't handle
316be649db0SIngo Weinhold		return B_UNSUPPORTED;
317be649db0SIngo Weinhold	}
318be649db0SIngo Weinhold
319be649db0SIngo Weinhold	status_t ReadFDEData(DataReader& dataReader,
320be649db0SIngo Weinhold		FDEAugmentation& fdeAugmentation)
321be649db0SIngo Weinhold	{
322be649db0SIngo Weinhold		if (!HasData())
323be649db0SIngo Weinhold			return B_OK;
324be649db0SIngo Weinhold
325be649db0SIngo Weinhold		// read the augmentation data block -- it is preceeded by an LEB128
326be649db0SIngo Weinhold		// indicating the length of the data block
327be649db0SIngo Weinhold		uint64 length = dataReader.ReadUnsignedLEB128(0);
328be649db0SIngo Weinhold		dataReader.Skip(length);
329be649db0SIngo Weinhold			// TODO: Actually read what is interesting for us!
330be649db0SIngo Weinhold
331be649db0SIngo Weinhold		TRACE_CFI("    %" B_PRIu64 " bytes of augmentation data\n", length);
332be649db0SIngo Weinhold
333be649db0SIngo Weinhold		if (dataReader.HasOverflow())
334be649db0SIngo Weinhold			return B_BAD_DATA;
335be649db0SIngo Weinhold
336be649db0SIngo Weinhold		return B_OK;
337be649db0SIngo Weinhold	}
338be649db0SIngo Weinhold
339be649db0SIngo Weinhold	const char* String() const
340be649db0SIngo Weinhold	{
341be649db0SIngo Weinhold		return fString;
342be649db0SIngo Weinhold	}
343be649db0SIngo Weinhold
344be649db0SIngo Weinhold	bool HasData() const
345be649db0SIngo Weinhold	{
346be649db0SIngo Weinhold		return (fFlags & CFI_AUGMENTATION_DATA) != 0;
347be649db0SIngo Weinhold	}
348be649db0SIngo Weinhold
349b5105244SRene Gollent	bool HasFDEAddressFormat() const
350b5105244SRene Gollent	{
351b5105244SRene Gollent		return (fFlags & CFI_AUGMENTATION_ADDRESS_POINTER_FORMAT) != 0;
352b5105244SRene Gollent	}
353b5105244SRene Gollent
35416b8573bSRene Gollent	target_addr_t FDEAddressOffset(ElfFile* file,
35516b8573bSRene Gollent		ElfSection* debugFrameSection) const
356b5105244SRene Gollent	{
357b5105244SRene Gollent		switch (FDEAddressType()) {
358b5105244SRene Gollent			case CFI_ADDRESS_FORMAT_ABSOLUTE:
35916b8573bSRene Gollent				TRACE_CFI("FDE address format: absolute, ");
36016b8573bSRene Gollent				return 0;
36196a4619bSRene Gollent			case CFI_ADDRESS_TYPE_PC_RELATIVE:
36216b8573bSRene Gollent				TRACE_CFI("FDE address format: PC relative, ");
36316b8573bSRene Gollent				return debugFrameSection->LoadAddress();
364b5105244SRene Gollent			case CFI_ADDRESS_TYPE_FUNCTION_RELATIVE:
36516b8573bSRene Gollent				TRACE_CFI("FDE address format: function relative, ");
366b5105244SRene Gollent				return 0;
367b5105244SRene Gollent			case CFI_ADDRESS_TYPE_TEXT_RELATIVE:
36816b8573bSRene Gollent				TRACE_CFI("FDE address format: text relative, ");
369b5105244SRene Gollent				return file->TextSegment()->LoadAddress();
370b5105244SRene Gollent			case CFI_ADDRESS_TYPE_DATA_RELATIVE:
37116b8573bSRene Gollent				TRACE_CFI("FDE address format: data relative, ");
372b5105244SRene Gollent				return file->DataSegment()->LoadAddress();
373b5105244SRene Gollent			case CFI_ADDRESS_TYPE_ALIGNED:
374b5105244SRene Gollent			case CFI_ADDRESS_TYPE_INDIRECT:
37516b8573bSRene Gollent				TRACE_CFI("FDE address format: UNIMPLEMENTED, ");
376b5105244SRene Gollent				// TODO: implement
377b5105244SRene Gollent				// -- note: type indirect is currently not generated
378b5105244SRene Gollent				return 0;
379b5105244SRene Gollent		}
380b5105244SRene Gollent
381b5105244SRene Gollent		return 0;
382b5105244SRene Gollent	}
383b5105244SRene Gollent
384b5105244SRene Gollent	uint8 FDEAddressType() const
385b5105244SRene Gollent	{
386b5105244SRene Gollent		return fAddressEncoding & 0x70;
387b5105244SRene Gollent	}
388b5105244SRene Gollent
389b5105244SRene Gollent	target_addr_t ReadEncodedAddress(DataReader &reader,
39016b8573bSRene Gollent		ElfFile* file, ElfSection* debugFrameSection,
39116b8573bSRene Gollent		bool valueOnly = false) const
392b5105244SRene Gollent	{
39316b8573bSRene Gollent		target_addr_t address = valueOnly ? 0 : FDEAddressOffset(file,
39416b8573bSRene Gollent			debugFrameSection);
395b5105244SRene Gollent		switch (fAddressEncoding & 0x0f) {
396b5105244SRene Gollent			case CFI_ADDRESS_FORMAT_ABSOLUTE:
397b5105244SRene Gollent				address += reader.ReadAddress(0);
39816b8573bSRene Gollent				TRACE_CFI(" target address: %" B_PRId64 "\n", address);
399b5105244SRene Gollent				break;
400b5105244SRene Gollent			case CFI_ADDRESS_FORMAT_UNSIGNED_LEB128:
401b5105244SRene Gollent				address += reader.ReadUnsignedLEB128(0);
40216b8573bSRene Gollent				TRACE_CFI(" unsigned LEB128: %" B_PRId64 "\n", address);
403b5105244SRene Gollent				break;
404b5105244SRene Gollent			case CFI_ADDRESS_FORMAT_SIGNED_LEB128:
405b5105244SRene Gollent				address += reader.ReadSignedLEB128(0);
40616b8573bSRene Gollent				TRACE_CFI(" signed LEB128: %" B_PRId64 "\n", address);
407b5105244SRene Gollent				break;
408b5105244SRene Gollent			case CFI_ADDRESS_FORMAT_UNSIGNED_16:
409b5105244SRene Gollent				address += reader.Read<uint16>(0);
41016b8573bSRene Gollent				TRACE_CFI(" unsigned 16-bit: %" B_PRId64 "\n", address);
411b5105244SRene Gollent				break;
412b5105244SRene Gollent			case CFI_ADDRESS_FORMAT_SIGNED_16:
413b5105244SRene Gollent				address += reader.Read<int16>(0);
41416b8573bSRene Gollent				TRACE_CFI(" signed 16-bit: %" B_PRId64 "\n", address);
415b5105244SRene Gollent				break;
416b5105244SRene Gollent			case CFI_ADDRESS_FORMAT_UNSIGNED_32:
417b5105244SRene Gollent				address += reader.Read<uint32>(0);
41816b8573bSRene Gollent				TRACE_CFI(" unsigned 32-bit: %" B_PRId64 "\n", address);
419b5105244SRene Gollent				break;
420b5105244SRene Gollent			case CFI_ADDRESS_FORMAT_SIGNED_32:
421b5105244SRene Gollent				address += reader.Read<int32>(0);
42216b8573bSRene Gollent				TRACE_CFI(" signed 32-bit: %" B_PRId64 "\n", address);
423b5105244SRene Gollent				break;
424b5105244SRene Gollent			case CFI_ADDRESS_FORMAT_UNSIGNED_64:
425b5105244SRene Gollent				address += reader.Read<uint64>(0);
42616b8573bSRene Gollent				TRACE_CFI(" unsigned 64-bit: %" B_PRId64 "\n", address);
427b5105244SRene Gollent				break;
428b5105244SRene Gollent			case CFI_ADDRESS_FORMAT_SIGNED_64:
429b5105244SRene Gollent				address += reader.Read<int64>(0);
43016b8573bSRene Gollent				TRACE_CFI(" signed 64-bit: %" B_PRId64 "\n", address);
431b5105244SRene Gollent				break;
432b5105244SRene Gollent		}
433b5105244SRene Gollent
434b5105244SRene Gollent		return address;
435b5105244SRene Gollent	}
436b5105244SRene Gollent
437b5105244SRene Gollent
438be649db0SIngo Weinholdprivate:
439be649db0SIngo Weinhold	const char*	fString;
440be649db0SIngo Weinhold	uint32		fFlags;
441b5105244SRene Gollent	int8		fAddressEncoding;
442be649db0SIngo Weinhold};
443be649db0SIngo Weinhold
444be649db0SIngo Weinhold
445d390ebeeSRene Gollent// #pragma mark - FDELookupInfo
446d390ebeeSRene Gollent
447d390ebeeSRene Gollent
448d390ebeeSRene Gollentstruct DwarfFile::FDELookupInfo {
449d390ebeeSRene Gollentpublic:
450d390ebeeSRene Gollent	FDELookupInfo(target_addr_t start, target_addr_t end,
451d390ebeeSRene Gollent		uint64 fdeOffset, uint64 cieOffset, bool ehFrame)
452d390ebeeSRene Gollent	:
453d390ebeeSRene Gollent	start(start),
454d390ebeeSRene Gollent	end(end),
455d390ebeeSRene Gollent	fdeOffset(fdeOffset),
456d390ebeeSRene Gollent	cieOffset(cieOffset),
457d390ebeeSRene Gollent	ehFrame(ehFrame)
458d390ebeeSRene Gollent	{
459d390ebeeSRene Gollent	}
460d390ebeeSRene Gollent
461d390ebeeSRene Gollent	static int CompareFDEInfos(const FDELookupInfo* a, const FDELookupInfo* b)
462d390ebeeSRene Gollent	{
463d390ebeeSRene Gollent		if (a->start < b->start)
464d390ebeeSRene Gollent			return -1;
465d390ebeeSRene Gollent		else if (a->start > b->start)
466d390ebeeSRene Gollent			return 1;
467d390ebeeSRene Gollent
468d390ebeeSRene Gollent		return 0;
469d390ebeeSRene Gollent	}
470d390ebeeSRene Gollent
471d390ebeeSRene Gollent	inline bool ContainsAddress(target_addr_t address) const
472d390ebeeSRene Gollent	{
473d390ebeeSRene Gollent		return address >= start && address < end;
474d390ebeeSRene Gollent	}
475d390ebeeSRene Gollent
476d390ebeeSRene Gollent	target_addr_t 		start;
477d390ebeeSRene Gollent	target_addr_t 		end;
478d390ebeeSRene Gollent	uint64				fdeOffset;
479d390ebeeSRene Gollent	uint64				cieOffset;
480d390ebeeSRene Gollent	bool				ehFrame;
481d390ebeeSRene Gollent};
482d390ebeeSRene Gollent
483d390ebeeSRene Gollent
484b312b9ffSIngo Weinhold// #pragma mark - DwarfFile
485b312b9ffSIngo Weinhold
486b312b9ffSIngo Weinhold
4877a7112b3SIngo WeinholdDwarfFile::DwarfFile()
4887a7112b3SIngo Weinhold	:
4897a7112b3SIngo Weinhold	fName(NULL),
490224f7510SRene Gollent	fAlternateName(NULL),
4917a7112b3SIngo Weinhold	fElfFile(NULL),
492224f7510SRene Gollent	fAlternateElfFile(NULL),
4937a7112b3SIngo Weinhold	fDebugInfoSection(NULL),
4947a7112b3SIngo Weinhold	fDebugAbbrevSection(NULL),
4957a7112b3SIngo Weinhold	fDebugStringSection(NULL),
4965b60969cSIngo Weinhold	fDebugRangesSection(NULL),
49791c6759fSIngo Weinhold	fDebugLineSection(NULL),
498f7526300SIngo Weinhold	fDebugFrameSection(NULL),
499dfa21dfeSRene Gollent	fEHFrameSection(NULL),
500d315bfd5SIngo Weinhold	fDebugLocationSection(NULL),
5016e72ebfcSIngo Weinhold	fDebugPublicTypesSection(NULL),
50271fec49eSRene Gollent	fDebugTypesSection(NULL),
5037c3612f4SIngo Weinhold	fCompilationUnits(20, true),
504d390ebeeSRene Gollent	fTypeUnits(),
505d390ebeeSRene Gollent	fDebugFrameInfos(100, true),
506d390ebeeSRene Gollent	fEHFrameInfos(100, true),
50771fec49eSRene Gollent	fTypesSectionRequired(false),
5087a7112b3SIngo Weinhold	fFinished(false),
509d390ebeeSRene Gollent	fItaniumEHFrameFormat(false),
5107a7112b3SIngo Weinhold	fFinishError(B_OK)
5117a7112b3SIngo Weinhold{
5127a7112b3SIngo Weinhold}
5137a7112b3SIngo Weinhold
5147a7112b3SIngo Weinhold
5157a7112b3SIngo WeinholdDwarfFile::~DwarfFile()
5167a7112b3SIngo Weinhold{
5177a7112b3SIngo Weinhold	while (AbbreviationTable* table = fAbbreviationTables.RemoveHead())
5187a7112b3SIngo Weinhold		delete table;
5197a7112b3SIngo Weinhold
5207a7112b3SIngo Weinhold	if (fElfFile != NULL) {
521224f7510SRene Gollent		ElfFile* debugInfoFile = fAlternateElfFile != NULL
522224f7510SRene Gollent			? fAlternateElfFile : fElfFile;
523224f7510SRene Gollent
524224f7510SRene Gollent		debugInfoFile->PutSection(fDebugInfoSection);
525224f7510SRene Gollent		debugInfoFile->PutSection(fDebugAbbrevSection);
526224f7510SRene Gollent		debugInfoFile->PutSection(fDebugStringSection);
527224f7510SRene Gollent		debugInfoFile->PutSection(fDebugRangesSection);
528224f7510SRene Gollent		debugInfoFile->PutSection(fDebugLineSection);
529224f7510SRene Gollent		debugInfoFile->PutSection(fDebugFrameSection);
530dfa21dfeSRene Gollent		fElfFile->PutSection(fEHFrameSection);
531224f7510SRene Gollent		debugInfoFile->PutSection(fDebugLocationSection);
532224f7510SRene Gollent		debugInfoFile->PutSection(fDebugPublicTypesSection);
5337a7112b3SIngo Weinhold		delete fElfFile;
534224f7510SRene Gollent		delete fAlternateElfFile;
5357a7112b3SIngo Weinhold	}
5367a7112b3SIngo Weinhold
537142f7cabSRene Gollent	TypeUnitTableEntry* entry = fTypeUnits.Clear(true);
538142f7cabSRene Gollent	while (entry != NULL) {
539142f7cabSRene Gollent		TypeUnitTableEntry* nextEntry = entry->next;
540142f7cabSRene Gollent		delete entry;
541142f7cabSRene Gollent		entry = nextEntry;
542142f7cabSRene Gollent	}
543142f7cabSRene Gollent
5447a7112b3SIngo Weinhold	free(fName);
545224f7510SRene Gollent	free(fAlternateName);
5467a7112b3SIngo Weinhold}
5477a7112b3SIngo Weinhold
5487a7112b3SIngo Weinhold
5497a7112b3SIngo Weinholdstatus_t
5507cab8329SRene GollentDwarfFile::StartLoading(const char* fileName, BString& _requiredExternalFile)
5517a7112b3SIngo Weinhold{
5527a7112b3SIngo Weinhold	fName = strdup(fileName);
5537a7112b3SIngo Weinhold	if (fName == NULL)
5547a7112b3SIngo Weinhold		return B_NO_MEMORY;
5557a7112b3SIngo Weinhold
55671fec49eSRene Gollent	status_t error = fTypeUnits.Init();
55771fec49eSRene Gollent	if (error != B_OK)
55871fec49eSRene Gollent		return error;
55971fec49eSRene Gollent
5607a7112b3SIngo Weinhold	// load the ELF file
5617a7112b3SIngo Weinhold	fElfFile = new(std::nothrow) ElfFile;
5627a7112b3SIngo Weinhold	if (fElfFile == NULL)
5637a7112b3SIngo Weinhold		return B_NO_MEMORY;
5647a7112b3SIngo Weinhold
56571fec49eSRene Gollent	error = fElfFile->Init(fileName);
5667a7112b3SIngo Weinhold	if (error != B_OK)
5677a7112b3SIngo Weinhold		return error;
5687a7112b3SIngo Weinhold
5697cab8329SRene Gollent	return _LocateDebugInfo(_requiredExternalFile);
5707cab8329SRene Gollent}
5717cab8329SRene Gollent
5727cab8329SRene Gollent
5737cab8329SRene Gollentstatus_t
574d390ebeeSRene GollentDwarfFile::Load(uint8 addressSize, const BString& externalInfoFilePath)
5757cab8329SRene Gollent{
5767cab8329SRene Gollent	status_t error = B_OK;
5777cab8329SRene Gollent	if (fDebugInfoSection == NULL) {
5787cab8329SRene Gollent		BString path;
5797cab8329SRene Gollent		error = _LocateDebugInfo(path, externalInfoFilePath.IsEmpty()
5807cab8329SRene Gollent				? NULL : externalInfoFilePath.String());
5817cab8329SRene Gollent		if (error != B_OK)
5827cab8329SRene Gollent			return error;
5837cab8329SRene Gollent	}
584224f7510SRene Gollent
585224f7510SRene Gollent	ElfFile* debugInfoFile = fAlternateElfFile != NULL
586224f7510SRene Gollent		? fAlternateElfFile : fElfFile;
5877a7112b3SIngo Weinhold
588f7526300SIngo Weinhold	// non mandatory sections
589224f7510SRene Gollent	fDebugStringSection = debugInfoFile->GetSection(".debug_str");
590224f7510SRene Gollent	fDebugRangesSection = debugInfoFile->GetSection(".debug_ranges");
591224f7510SRene Gollent	fDebugLineSection = debugInfoFile->GetSection(".debug_line");
592224f7510SRene Gollent	fDebugFrameSection = debugInfoFile->GetSection(".debug_frame");
593d390ebeeSRene Gollent
594d390ebeeSRene Gollent	if (fDebugFrameSection != NULL) {
595d390ebeeSRene Gollent		error = _ParseFrameSection(fDebugFrameSection, addressSize, false,
596d390ebeeSRene Gollent			fDebugFrameInfos);
597d390ebeeSRene Gollent		if (error != B_OK)
598d390ebeeSRene Gollent			return error;
599d390ebeeSRene Gollent	}
600d390ebeeSRene Gollent
601224f7510SRene Gollent	// .eh_frame doesn't appear to get copied into separate debug
602224f7510SRene Gollent	// info files properly, therefore always use it off the main
603224f7510SRene Gollent	// executable image
6045bda396eSRene Gollent	if (fEHFrameSection == NULL)
6055bda396eSRene Gollent		fEHFrameSection = fElfFile->GetSection(".eh_frame");
606d390ebeeSRene Gollent
607d390ebeeSRene Gollent	if (fEHFrameSection != NULL) {
608d390ebeeSRene Gollent		error = _ParseFrameSection(fEHFrameSection, addressSize, true,
609d390ebeeSRene Gollent			fEHFrameInfos);
610d390ebeeSRene Gollent		if (error != B_OK)
611d390ebeeSRene Gollent			return error;
612d390ebeeSRene Gollent	}
613d390ebeeSRene Gollent
614224f7510SRene Gollent	fDebugLocationSection = debugInfoFile->GetSection(".debug_loc");
615224f7510SRene Gollent	fDebugPublicTypesSection = debugInfoFile->GetSection(".debug_pubtypes");
61691c6759fSIngo Weinhold
6175bda396eSRene Gollent	if (fDebugInfoSection == NULL) {
6185bda396eSRene Gollent		fFinished = true;
6195bda396eSRene Gollent		return B_OK;
6205bda396eSRene Gollent	}
6215bda396eSRene Gollent
62271fec49eSRene Gollent	error = _ParseDebugInfoSection();
62371fec49eSRene Gollent	if (error != B_OK)
62471fec49eSRene Gollent		return error;
6257a7112b3SIngo Weinhold
62671fec49eSRene Gollent	if (fTypesSectionRequired) {
62771fec49eSRene Gollent		fDebugTypesSection = debugInfoFile->GetSection(".debug_types");
62871fec49eSRene Gollent		if (fDebugTypesSection == NULL) {
62971fec49eSRene Gollent			WARNING(".debug_types section required but missing.\n");
63071fec49eSRene Gollent			return B_BAD_DATA;
6317c3612f4SIngo Weinhold		}
63271fec49eSRene Gollent		error = _ParseTypesSection();
6337a7112b3SIngo Weinhold		if (error != B_OK)
6347a7112b3SIngo Weinhold			return error;
6357a7112b3SIngo Weinhold	}
6367a7112b3SIngo Weinhold
6377a7112b3SIngo Weinhold	return B_OK;
6387a7112b3SIngo Weinhold}
6397a7112b3SIngo Weinhold
6407a7112b3SIngo Weinhold
6417a7112b3SIngo Weinholdstatus_t
6427a7112b3SIngo WeinholdDwarfFile::FinishLoading()
6437a7112b3SIngo Weinhold{
6447a7112b3SIngo Weinhold	if (fFinished)
6457a7112b3SIngo Weinhold		return B_OK;
6467a7112b3SIngo Weinhold	if (fFinishError != B_OK)
6477a7112b3SIngo Weinhold		return fFinishError;
6487a7112b3SIngo Weinhold
64971fec49eSRene Gollent	status_t error;
650fe07d32cSRene Gollent	for (TypeUnitTable::Iterator it = fTypeUnits.GetIterator();
651fe07d32cSRene Gollent		TypeUnitTableEntry* entry = it.Next();) {
652fe07d32cSRene Gollent		error = _FinishUnit(entry->unit);
65371fec49eSRene Gollent		if (error != B_OK)
65471fec49eSRene Gollent			return fFinishError = error;
65571fec49eSRene Gollent	}
65671fec49eSRene Gollent
657fe07d32cSRene Gollent	for (int32 i = 0; CompilationUnit* unit = fCompilationUnits.ItemAt(i);
658fe07d32cSRene Gollent			i++) {
659fe07d32cSRene Gollent		error = _FinishUnit(unit);
6607a7112b3SIngo Weinhold		if (error != B_OK)
6617a7112b3SIngo Weinhold			return fFinishError = error;
6627a7112b3SIngo Weinhold	}
6637a7112b3SIngo Weinhold
6646e72ebfcSIngo Weinhold	_ParsePublicTypesInfo();
6656e72ebfcSIngo Weinhold
6667a7112b3SIngo Weinhold	fFinished = true;
6677a7112b3SIngo Weinhold	return B_OK;
6687a7112b3SIngo Weinhold}
6697a7112b3SIngo Weinhold
6707a7112b3SIngo Weinhold
6717c3612f4SIngo Weinholdint32
6727c3612f4SIngo WeinholdDwarfFile::CountCompilationUnits() const
6737c3612f4SIngo Weinhold{
6747c3612f4SIngo Weinhold	return fCompilationUnits.CountItems();
6757c3612f4SIngo Weinhold}
6767c3612f4SIngo Weinhold
6777c3612f4SIngo Weinhold
6787c3612f4SIngo WeinholdCompilationUnit*
6797c3612f4SIngo WeinholdDwarfFile::CompilationUnitAt(int32 index) const
6807c3612f4SIngo Weinhold{
6817c3612f4SIngo Weinhold	return fCompilationUnits.ItemAt(index);
6827c3612f4SIngo Weinhold}
6837c3612f4SIngo Weinhold
6847c3612f4SIngo Weinhold
68591c6759fSIngo WeinholdCompilationUnit*
68691c6759fSIngo WeinholdDwarfFile::CompilationUnitForDIE(const DebugInfoEntry* entry) const
68791c6759fSIngo Weinhold{
68891c6759fSIngo Weinhold	// find the root of the tree the entry lives in
68991c6759fSIngo Weinhold	while (entry != NULL && entry->Parent() != NULL)
69091c6759fSIngo Weinhold		entry = entry->Parent();
69191c6759fSIngo Weinhold
69291c6759fSIngo Weinhold	// that should be the compilation unit entry
69391c6759fSIngo Weinhold	const DIECompileUnitBase* unitEntry
69491c6759fSIngo Weinhold		= dynamic_cast<const DIECompileUnitBase*>(entry);
69591c6759fSIngo Weinhold	if (unitEntry == NULL)
69691c6759fSIngo Weinhold		return NULL;
69791c6759fSIngo Weinhold
69891c6759fSIngo Weinhold	// find the compilation unit
69991c6759fSIngo Weinhold	for (int32 i = 0; CompilationUnit* unit = fCompilationUnits.ItemAt(i);
70091c6759fSIngo Weinhold			i++) {
70191c6759fSIngo Weinhold		if (unit->UnitEntry() == unitEntry)
70291c6759fSIngo Weinhold			return unit;
70391c6759fSIngo Weinhold	}
70491c6759fSIngo Weinhold
70591c6759fSIngo Weinhold	return NULL;
70691c6759fSIngo Weinhold}
70791c6759fSIngo Weinhold
70891c6759fSIngo Weinhold
7093c33a74cSIngo WeinholdTargetAddressRangeList*
7103c33a74cSIngo WeinholdDwarfFile::ResolveRangeList(CompilationUnit* unit, uint64 offset) const
7113c33a74cSIngo Weinhold{
7123c33a74cSIngo Weinhold	if (unit == NULL || fDebugRangesSection == NULL)
7133c33a74cSIngo Weinhold		return NULL;
7143c33a74cSIngo Weinhold
715f78b08d8STheodore Kokkoris	if (offset >= (uint64)fDebugRangesSection->Size())
7163c33a74cSIngo Weinhold		return NULL;
7173c33a74cSIngo Weinhold
7183c33a74cSIngo Weinhold	TargetAddressRangeList* ranges = new(std::nothrow) TargetAddressRangeList;
7193c33a74cSIngo Weinhold	if (ranges == NULL) {
7206e72ebfcSIngo Weinhold		ERROR("Out of memory.\n");
7213c33a74cSIngo Weinhold		return NULL;
7223c33a74cSIngo Weinhold	}
723c3e066cfSIngo Weinhold	BReference<TargetAddressRangeList> rangesReference(ranges, true);
7243c33a74cSIngo Weinhold
7253c33a74cSIngo Weinhold	target_addr_t baseAddress = unit->AddressRangeBase();
7263c33a74cSIngo Weinhold	target_addr_t maxAddress = unit->MaxAddress();
7273c33a74cSIngo Weinhold
7283c33a74cSIngo Weinhold	DataReader dataReader((uint8*)fDebugRangesSection->Data() + offset,
7293c33a74cSIngo Weinhold		fDebugRangesSection->Size() - offset, unit->AddressSize());
7303c33a74cSIngo Weinhold	while (true) {
7313c33a74cSIngo Weinhold		target_addr_t start = dataReader.ReadAddress(0);
7323c33a74cSIngo Weinhold		target_addr_t end = dataReader.ReadAddress(0);
7333c33a74cSIngo Weinhold		if (dataReader.HasOverflow())
7343c33a74cSIngo Weinhold			return NULL;
7353c33a74cSIngo Weinhold
7363c33a74cSIngo Weinhold		if (start == 0 && end == 0)
7373c33a74cSIngo Weinhold			break;
7383c33a74cSIngo Weinhold		if (start == maxAddress) {
7393c33a74cSIngo Weinhold			baseAddress = end;
7403c33a74cSIngo Weinhold			continue;
7413c33a74cSIngo Weinhold		}
7423c33a74cSIngo Weinhold		if (start == end)
7433c33a74cSIngo Weinhold			continue;
7443c33a74cSIngo Weinhold
7453c33a74cSIngo Weinhold		if (!ranges->AddRange(baseAddress + start, end - start)) {
7466e72ebfcSIngo Weinhold			ERROR("Out of memory.\n");
7473c33a74cSIngo Weinhold			return NULL;
7483c33a74cSIngo Weinhold		}
7493c33a74cSIngo Weinhold	}
7503c33a74cSIngo Weinhold
7513c33a74cSIngo Weinhold	return rangesReference.Detach();
7523c33a74cSIngo Weinhold}
7533c33a74cSIngo Weinhold
7543c33a74cSIngo Weinhold
755f7526300SIngo Weinholdstatus_t
7565bda396eSRene GollentDwarfFile::UnwindCallFrame(CompilationUnit* unit, uint8 addressSize,
757d315bfd5SIngo Weinhold	DIESubprogram* subprogramEntry, target_addr_t location,
758f7526300SIngo Weinhold	const DwarfTargetInterface* inputInterface,
759f7526300SIngo Weinhold	DwarfTargetInterface* outputInterface, target_addr_t& _framePointer)
760f7526300SIngo Weinhold{
761d390ebeeSRene Gollent	FDELookupInfo* info = _GetContainingFDEInfo(location);
762d390ebeeSRene Gollent	if (info == NULL)
763d390ebeeSRene Gollent		return B_ENTRY_NOT_FOUND;
764f7526300SIngo Weinhold
765d390ebeeSRene Gollent	return _UnwindCallFrame(unit, addressSize, subprogramEntry, location, info,
766d390ebeeSRene Gollent		inputInterface, outputInterface, _framePointer);
767f7526300SIngo Weinhold}
768f7526300SIngo Weinhold
769f7526300SIngo Weinhold
770d315bfd5SIngo Weinholdstatus_t
77116b8573bSRene GollentDwarfFile::EvaluateExpression(CompilationUnit* unit, uint8 addressSize,
772d315bfd5SIngo Weinhold	DIESubprogram* subprogramEntry, const void* expression,
773d315bfd5SIngo Weinhold	off_t expressionLength, const DwarfTargetInterface* targetInterface,
774d315bfd5SIngo Weinhold	target_addr_t instructionPointer, target_addr_t framePointer,
775d315bfd5SIngo Weinhold	target_addr_t valueToPush, bool pushValue, target_addr_t& _result)
776d315bfd5SIngo Weinhold{
77716b8573bSRene Gollent	ExpressionEvaluationContext context(this, unit, addressSize,
77816b8573bSRene Gollent		subprogramEntry, targetInterface, instructionPointer, 0, false,
77916b8573bSRene Gollent		framePointer, 0);
780d315bfd5SIngo Weinhold	DwarfExpressionEvaluator evaluator(&context);
781d315bfd5SIngo Weinhold
782d315bfd5SIngo Weinhold	if (pushValue && evaluator.Push(valueToPush) != B_OK)
783d315bfd5SIngo Weinhold		return B_NO_MEMORY;
784d315bfd5SIngo Weinhold
785d315bfd5SIngo Weinhold	return evaluator.Evaluate(expression, expressionLength, _result);
786d315bfd5SIngo Weinhold}
787d315bfd5SIngo Weinhold
788d315bfd5SIngo Weinhold
789d315bfd5SIngo Weinholdstatus_t
79016b8573bSRene GollentDwarfFile::ResolveLocation(CompilationUnit* unit, uint8 addressSize,
791d315bfd5SIngo Weinhold	DIESubprogram* subprogramEntry, const LocationDescription* location,
792d315bfd5SIngo Weinhold	const DwarfTargetInterface* targetInterface,
793d315bfd5SIngo Weinhold	target_addr_t instructionPointer, target_addr_t objectPointer,
7940573015dSRene Gollent	bool hasObjectPointer, target_addr_t framePointer,
7950573015dSRene Gollent	target_addr_t relocationDelta, ValueLocation& _result)
796d315bfd5SIngo Weinhold{
797d315bfd5SIngo Weinhold	// get the expression
798d315bfd5SIngo Weinhold	const void* expression;
799d315bfd5SIngo Weinhold	off_t expressionLength;
800d315bfd5SIngo Weinhold	status_t error = _GetLocationExpression(unit, location, instructionPointer,
801d315bfd5SIngo Weinhold		expression, expressionLength);
802d315bfd5SIngo Weinhold	if (error != B_OK)
803d315bfd5SIngo Weinhold		return error;
804d315bfd5SIngo Weinhold
805d315bfd5SIngo Weinhold	// evaluate it
80616b8573bSRene Gollent	ExpressionEvaluationContext context(this, unit, addressSize,
80716b8573bSRene Gollent		subprogramEntry, targetInterface, instructionPointer, objectPointer,
80816b8573bSRene Gollent		hasObjectPointer, framePointer, relocationDelta);
809d315bfd5SIngo Weinhold	DwarfExpressionEvaluator evaluator(&context);
8101a5bb78dSRene Gollent	return evaluator.EvaluateLocation(expression, expressionLength,
8111a5bb78dSRene Gollent		_result);
812d315bfd5SIngo Weinhold}
813d315bfd5SIngo Weinhold
814d315bfd5SIngo Weinhold
815d315bfd5SIngo Weinholdstatus_t
81616b8573bSRene GollentDwarfFile::EvaluateConstantValue(CompilationUnit* unit, uint8 addressSize,
817d315bfd5SIngo Weinhold	DIESubprogram* subprogramEntry, const ConstantAttributeValue* value,
818d315bfd5SIngo Weinhold	const DwarfTargetInterface* targetInterface,
819d315bfd5SIngo Weinhold	target_addr_t instructionPointer, target_addr_t framePointer,
820d315bfd5SIngo Weinhold	BVariant& _result)
821d315bfd5SIngo Weinhold{
822d315bfd5SIngo Weinhold	if (!value->IsValid())
823d315bfd5SIngo Weinhold		return B_BAD_VALUE;
824d315bfd5SIngo Weinhold
825d315bfd5SIngo Weinhold	switch (value->attributeClass) {
826d315bfd5SIngo Weinhold		case ATTRIBUTE_CLASS_CONSTANT:
827d315bfd5SIngo Weinhold			_result.SetTo(value->constant);
828d315bfd5SIngo Weinhold			return B_OK;
829d315bfd5SIngo Weinhold		case ATTRIBUTE_CLASS_STRING:
830d315bfd5SIngo Weinhold			_result.SetTo(value->string);
831d315bfd5SIngo Weinhold			return B_OK;
832d315bfd5SIngo Weinhold		case ATTRIBUTE_CLASS_BLOCK:
833d315bfd5SIngo Weinhold		{
834d315bfd5SIngo Weinhold			target_addr_t result;
83516b8573bSRene Gollent			status_t error = EvaluateExpression(unit, addressSize,
83616b8573bSRene Gollent				subprogramEntry, value->block.data, value->block.length,
83716b8573bSRene Gollent				targetInterface, instructionPointer, framePointer, 0, false,
83816b8573bSRene Gollent				result);
839d315bfd5SIngo Weinhold			if (error != B_OK)
840d315bfd5SIngo Weinhold				return error;
841d315bfd5SIngo Weinhold
842d315bfd5SIngo Weinhold			_result.SetTo(result);
843d315bfd5SIngo Weinhold			return B_OK;
844d315bfd5SIngo Weinhold		}
845d315bfd5SIngo Weinhold		default:
846d315bfd5SIngo Weinhold			return B_BAD_VALUE;
847d315bfd5SIngo Weinhold	}
848d315bfd5SIngo Weinhold}
849d315bfd5SIngo Weinhold
850d315bfd5SIngo Weinhold
851d315bfd5SIngo Weinholdstatus_t
85216b8573bSRene GollentDwarfFile::EvaluateDynamicValue(CompilationUnit* unit, uint8 addressSize,
853d315bfd5SIngo Weinhold	DIESubprogram* subprogramEntry, const DynamicAttributeValue* value,
854d315bfd5SIngo Weinhold	const DwarfTargetInterface* targetInterface,
855d315bfd5SIngo Weinhold	target_addr_t instructionPointer, target_addr_t framePointer,
8567d82c6ddSIngo Weinhold	BVariant& _result, DIEType** _type)
857d315bfd5SIngo Weinhold{
858d315bfd5SIngo Weinhold	if (!value->IsValid())
859d315bfd5SIngo Weinhold		return B_BAD_VALUE;
860d315bfd5SIngo Weinhold
8617d82c6ddSIngo Weinhold	DIEType* dummyType;
8627d82c6ddSIngo Weinhold	if (_type == NULL)
8637d82c6ddSIngo Weinhold		_type = &dummyType;
8647d82c6ddSIngo Weinhold
865d315bfd5SIngo Weinhold	switch (value->attributeClass) {
866d315bfd5SIngo Weinhold		case ATTRIBUTE_CLASS_CONSTANT:
867d315bfd5SIngo Weinhold			_result.SetTo(value->constant);
8687d82c6ddSIngo Weinhold			*_type = NULL;
869d315bfd5SIngo Weinhold			return B_OK;
870d315bfd5SIngo Weinhold
871d315bfd5SIngo Weinhold		case ATTRIBUTE_CLASS_REFERENCE:
872d315bfd5SIngo Weinhold		{
873d315bfd5SIngo Weinhold			// TODO: The specs are a bit fuzzy on this one: "the value is a
874d315bfd5SIngo Weinhold			// reference to another entity whose value is the value of the
875d315bfd5SIngo Weinhold			// attribute". Supposedly that also means e.g. if the referenced
876d315bfd5SIngo Weinhold			// entity is a variable, we should read the value of that variable.
877d315bfd5SIngo Weinhold			// ATM we only check for the types that can have a DW_AT_const_value
878d315bfd5SIngo Weinhold			// attribute and evaluate it, if present.
879d315bfd5SIngo Weinhold			DebugInfoEntry* entry = value->reference;
880d315bfd5SIngo Weinhold			if (entry == NULL)
881d315bfd5SIngo Weinhold				return B_BAD_VALUE;
882d315bfd5SIngo Weinhold
883d315bfd5SIngo Weinhold			const ConstantAttributeValue* constantValue = NULL;
8847d82c6ddSIngo Weinhold			DIEType* type = NULL;
885d315bfd5SIngo Weinhold
886d315bfd5SIngo Weinhold			switch (entry->Tag()) {
887d315bfd5SIngo Weinhold				case DW_TAG_constant:
8887d82c6ddSIngo Weinhold				{
8897d82c6ddSIngo Weinhold					DIEConstant* constantEntry
8907d82c6ddSIngo Weinhold						= dynamic_cast<DIEConstant*>(entry);
8917d82c6ddSIngo Weinhold					constantValue = constantEntry->ConstValue();
8927d82c6ddSIngo Weinhold					type = constantEntry->GetType();
893d315bfd5SIngo Weinhold					break;
8947d82c6ddSIngo Weinhold				}
895d315bfd5SIngo Weinhold				case DW_TAG_enumerator:
896d315bfd5SIngo Weinhold					constantValue = dynamic_cast<DIEEnumerator*>(entry)
897d315bfd5SIngo Weinhold						->ConstValue();
8987d82c6ddSIngo Weinhold					if (DIEEnumerationType* enumerationType
8997d82c6ddSIngo Weinhold							= dynamic_cast<DIEEnumerationType*>(
9007d82c6ddSIngo Weinhold								entry->Parent())) {
9017d82c6ddSIngo Weinhold						type = enumerationType->GetType();
9027d82c6ddSIngo Weinhold					}
903d315bfd5SIngo Weinhold					break;
904d315bfd5SIngo Weinhold				case DW_TAG_formal_parameter:
9057d82c6ddSIngo Weinhold				{
9067d82c6ddSIngo Weinhold					DIEFormalParameter* parameterEntry
9077d82c6ddSIngo Weinhold						= dynamic_cast<DIEFormalParameter*>(entry);
9087d82c6ddSIngo Weinhold					constantValue = parameterEntry->ConstValue();
9097d82c6ddSIngo Weinhold					type = parameterEntry->GetType();
910d315bfd5SIngo Weinhold					break;
9117d82c6ddSIngo Weinhold				}
912d315bfd5SIngo Weinhold				case DW_TAG_template_value_parameter:
9137d82c6ddSIngo Weinhold				{
9147d82c6ddSIngo Weinhold					DIETemplateValueParameter* parameterEntry
9157d82c6ddSIngo Weinhold						= dynamic_cast<DIETemplateValueParameter*>(entry);
9167d82c6ddSIngo Weinhold					constantValue = parameterEntry->ConstValue();
9177d82c6ddSIngo Weinhold					type = parameterEntry->GetType();
918d315bfd5SIngo Weinhold					break;
9197d82c6ddSIngo Weinhold				}
920d315bfd5SIngo Weinhold				case DW_TAG_variable:
9217d82c6ddSIngo Weinhold				{
9227d82c6ddSIngo Weinhold					DIEVariable* variableEntry
9237d82c6ddSIngo Weinhold						= dynamic_cast<DIEVariable*>(entry);
9247d82c6ddSIngo Weinhold					constantValue = variableEntry->ConstValue();
9257d82c6ddSIngo Weinhold					type = variableEntry->GetType();
926d315bfd5SIngo Weinhold					break;
9277d82c6ddSIngo Weinhold				}
928d315bfd5SIngo Weinhold				default:
929d315bfd5SIngo Weinhold					return B_BAD_VALUE;
930d315bfd5SIngo Weinhold			}
931d315bfd5SIngo Weinhold
932d315bfd5SIngo Weinhold			if (constantValue == NULL || !constantValue->IsValid())
933d315bfd5SIngo Weinhold				return B_BAD_VALUE;
934d315bfd5SIngo Weinhold
93516b8573bSRene Gollent			status_t error = EvaluateConstantValue(unit, addressSize,
93616b8573bSRene Gollent				subprogramEntry, constantValue, targetInterface,
93716b8573bSRene Gollent				instructionPointer, framePointer, _result);
9387d82c6ddSIngo Weinhold			if (error != B_OK)
9397d82c6ddSIngo Weinhold				return error;
9407d82c6ddSIngo Weinhold
9417d82c6ddSIngo Weinhold			*_type = type;
9427d82c6ddSIngo Weinhold			return B_OK;
943d315bfd5SIngo Weinhold		}
944d315bfd5SIngo Weinhold
945d315bfd5SIngo Weinhold		case ATTRIBUTE_CLASS_BLOCK:
946d315bfd5SIngo Weinhold		{
947d315bfd5SIngo Weinhold			target_addr_t result;
94816b8573bSRene Gollent			status_t error = EvaluateExpression(unit, addressSize,
94916b8573bSRene Gollent				subprogramEntry, value->block.data, value->block.length,
95016b8573bSRene Gollent				targetInterface, instructionPointer, framePointer, 0, false,
95116b8573bSRene Gollent				result);
952d315bfd5SIngo Weinhold			if (error != B_OK)
953d315bfd5SIngo Weinhold				return error;
954d315bfd5SIngo Weinhold
955d315bfd5SIngo Weinhold			_result.SetTo(result);
9567d82c6ddSIngo Weinhold			*_type = NULL;
957d315bfd5SIngo Weinhold			return B_OK;
958d315bfd5SIngo Weinhold		}
959d315bfd5SIngo Weinhold
960d315bfd5SIngo Weinhold		default:
961d315bfd5SIngo Weinhold			return B_BAD_VALUE;
962d315bfd5SIngo Weinhold	}
963d315bfd5SIngo Weinhold}
964d315bfd5SIngo Weinhold
965d315bfd5SIngo Weinhold
96671fec49eSRene Gollentstatus_t
96771fec49eSRene GollentDwarfFile::_ParseDebugInfoSection()
96871fec49eSRene Gollent{
96971fec49eSRene Gollent	// iterate through the debug info section
97071fec49eSRene Gollent	DataReader dataReader(fDebugInfoSection->Data(),
97171fec49eSRene Gollent		fDebugInfoSection->Size(), 4);
97271fec49eSRene Gollent			// address size doesn't matter here
97371fec49eSRene Gollent	while (dataReader.HasData()) {
97471fec49eSRene Gollent		off_t unitHeaderOffset = dataReader.Offset();
97571fec49eSRene Gollent		bool dwarf64;
97671fec49eSRene Gollent		uint64 unitLength = dataReader.ReadInitialLength(dwarf64);
97771fec49eSRene Gollent
97871fec49eSRene Gollent		off_t unitLengthOffset = dataReader.Offset();
97971fec49eSRene Gollent			// the unitLength starts here
98071fec49eSRene Gollent
98171fec49eSRene Gollent		if (unitLengthOffset + unitLength
98271fec49eSRene Gollent				> (uint64)fDebugInfoSection->Size()) {
98371fec49eSRene Gollent			WARNING("\"%s\": Invalid compilation unit length.\n", fName);
98471fec49eSRene Gollent			break;
98571fec49eSRene Gollent		}
98671fec49eSRene Gollent
98771fec49eSRene Gollent		int version = dataReader.Read<uint16>(0);
98871fec49eSRene Gollent		off_t abbrevOffset = dwarf64
98971fec49eSRene Gollent			? dataReader.Read<uint64>(0)
99071fec49eSRene Gollent			: dataReader.Read<uint32>(0);
99171fec49eSRene Gollent		uint8 addressSize = dataReader.Read<uint8>(0);
99271fec49eSRene Gollent
99371fec49eSRene Gollent		if (dataReader.HasOverflow()) {
99471fec49eSRene Gollent			WARNING("\"%s\": Unexpected end of data in compilation unit "
99571fec49eSRene Gollent				"header.\n", fName);
99671fec49eSRene Gollent			break;
99771fec49eSRene Gollent		}
99871fec49eSRene Gollent
99971fec49eSRene Gollent		TRACE_DIE("DWARF%d compilation unit: version %d, length: %" B_PRIu64
100071fec49eSRene Gollent			", abbrevOffset: %" B_PRIdOFF ", address size: %d\n",
100171fec49eSRene Gollent			dwarf64 ? 64 : 32, version, unitLength, abbrevOffset, addressSize);
100271fec49eSRene Gollent
100371fec49eSRene Gollent		if (version < 2 || version > 4) {
100471fec49eSRene Gollent			WARNING("\"%s\": Unsupported compilation unit version: %d\n",
100571fec49eSRene Gollent				fName, version);
100671fec49eSRene Gollent			break;
100771fec49eSRene Gollent		}
100871fec49eSRene Gollent
100971fec49eSRene Gollent		if (addressSize != 4 && addressSize != 8) {
101071fec49eSRene Gollent			WARNING("\"%s\": Unsupported address size: %d\n", fName,
101171fec49eSRene Gollent				addressSize);
101271fec49eSRene Gollent			break;
101371fec49eSRene Gollent		}
101471fec49eSRene Gollent		dataReader.SetAddressSize(addressSize);
101571fec49eSRene Gollent
101671fec49eSRene Gollent		off_t unitContentOffset = dataReader.Offset();
101771fec49eSRene Gollent
101871fec49eSRene Gollent		// create a compilation unit object
101971fec49eSRene Gollent		CompilationUnit* unit = new(std::nothrow) CompilationUnit(
102071fec49eSRene Gollent			unitHeaderOffset, unitContentOffset,
102171fec49eSRene Gollent			unitLength + (unitLengthOffset - unitHeaderOffset),
102271fec49eSRene Gollent			abbrevOffset, addressSize, dwarf64);
102371fec49eSRene Gollent		if (unit == NULL || !fCompilationUnits.AddItem(unit)) {
102471fec49eSRene Gollent			delete unit;
102571fec49eSRene Gollent			return B_NO_MEMORY;
102671fec49eSRene Gollent		}
102771fec49eSRene Gollent
102871fec49eSRene Gollent		// parse the debug info for the unit
102971fec49eSRene Gollent		status_t error = _ParseCompilationUnit(unit);
103071fec49eSRene Gollent		if (error != B_OK)
103171fec49eSRene Gollent			return error;
103271fec49eSRene Gollent
103371fec49eSRene Gollent		dataReader.SeekAbsolute(unitLengthOffset + unitLength);
103471fec49eSRene Gollent	}
103571fec49eSRene Gollent
103671fec49eSRene Gollent	return B_OK;
103771fec49eSRene Gollent}
103871fec49eSRene Gollent
103971fec49eSRene Gollent
104071fec49eSRene Gollentstatus_t
104171fec49eSRene GollentDwarfFile::_ParseTypesSection()
104271fec49eSRene Gollent{
104371fec49eSRene Gollent	DataReader dataReader(fDebugTypesSection->Data(),
104471fec49eSRene Gollent		fDebugTypesSection->Size(), 4);
104571fec49eSRene Gollent	while (dataReader.HasData()) {
104671fec49eSRene Gollent		off_t unitHeaderOffset = dataReader.Offset();
104771fec49eSRene Gollent		bool dwarf64;
104871fec49eSRene Gollent		uint64 unitLength = dataReader.ReadInitialLength(dwarf64);
104971fec49eSRene Gollent
105071fec49eSRene Gollent		off_t unitLengthOffset = dataReader.Offset();
105171fec49eSRene Gollent			// the unitLength starts here
105271fec49eSRene Gollent
105371fec49eSRene Gollent		if (unitLengthOffset + unitLength
105471fec49eSRene Gollent				> (uint64)fDebugTypesSection->Size()) {
105571fec49eSRene Gollent			WARNING("Invalid type unit length, offset %#" B_PRIx64 ".\n",
105671fec49eSRene Gollent				unitHeaderOffset);
105771fec49eSRene Gollent			break;
105871fec49eSRene Gollent		}
105971fec49eSRene Gollent
106071fec49eSRene Gollent		int version = dataReader.Read<uint16>(0);
106171fec49eSRene Gollent		off_t abbrevOffset = dwarf64
106271fec49eSRene Gollent			? dataReader.Read<uint64>(0)
106371fec49eSRene Gollent			: dataReader.Read<uint32>(0);
106471fec49eSRene Gollent		uint8 addressSize = dataReader.Read<uint8>(0);
106571fec49eSRene Gollent
106671fec49eSRene Gollent		if (dataReader.HasOverflow()) {
106771fec49eSRene Gollent			WARNING("Unexpected end of data in type unit header at %#"
106871fec49eSRene Gollent				B_PRIx64 ".\n", unitHeaderOffset);
106971fec49eSRene Gollent			break;
107071fec49eSRene Gollent		}
107171fec49eSRene Gollent
1072a5bee836SRene Gollent		dataReader.SetAddressSize(addressSize);
1073a5bee836SRene Gollent
1074a5bee836SRene Gollent		uint64 signature = dataReader.Read<uint64>(0);
1075a5bee836SRene Gollent
1076a5bee836SRene Gollent		off_t typeOffset = dwarf64
1077a5bee836SRene Gollent			? dataReader.Read<uint64>(0)
1078a5bee836SRene Gollent			: dataReader.Read<uint32>(0);
1079a5bee836SRene Gollent
1080a5bee836SRene Gollent		off_t unitContentOffset = dataReader.Offset();
1081a5bee836SRene Gollent
108271fec49eSRene Gollent		TRACE_DIE("DWARF%d type unit: version %d, length: %" B_PRIu64
1083a5bee836SRene Gollent			", abbrevOffset: %" B_PRIdOFF ", address size: %d, "
1084a5bee836SRene Gollent			"signature: %#" B_PRIx64 ", type offset: %" B_PRIu64 "\n",
1085a5bee836SRene Gollent			dwarf64 ? 64 : 32, version, unitLength, abbrevOffset, addressSize,
1086a5bee836SRene Gollent			signature, typeOffset);
108771fec49eSRene Gollent
108871fec49eSRene Gollent		if (version > 4) {
108971fec49eSRene Gollent			WARNING("\"%s\": Unsupported type unit version: %d\n",
109071fec49eSRene Gollent				fName, version);
109171fec49eSRene Gollent			break;
109271fec49eSRene Gollent		}
109371fec49eSRene Gollent
109471fec49eSRene Gollent		if (addressSize != 4 && addressSize != 8) {
109571fec49eSRene Gollent			WARNING("\"%s\": Unsupported address size: %d\n", fName,
109671fec49eSRene Gollent				addressSize);
109771fec49eSRene Gollent			break;
109871fec49eSRene Gollent		}
109971fec49eSRene Gollent
110071fec49eSRene Gollent		// create a type unit object
110171fec49eSRene Gollent		TypeUnit* unit = new(std::nothrow) TypeUnit(
110271fec49eSRene Gollent			unitHeaderOffset, unitContentOffset,
110371fec49eSRene Gollent			unitLength + (unitLengthOffset - unitHeaderOffset),
110471fec49eSRene Gollent			abbrevOffset, typeOffset, addressSize, signature, dwarf64);
11054c901476SAdrien Destugues		if (unit == NULL)
110671fec49eSRene Gollent			return B_NO_MEMORY;
110771fec49eSRene Gollent
110871fec49eSRene Gollent		// parse the debug info for the unit
110971fec49eSRene Gollent		status_t error = _ParseTypeUnit(unit);
111071fec49eSRene Gollent		if (error != B_OK)
111171fec49eSRene Gollent			return error;
111271fec49eSRene Gollent
111371fec49eSRene Gollent		// TODO: it should theoretically never happen that we get a duplicate,
111471fec49eSRene Gollent		// but it wouldn't hurt to check since that situation would potentially
111571fec49eSRene Gollent		// be problematic.
111671fec49eSRene Gollent		if (fTypeUnits.Lookup(signature) == NULL) {
111771fec49eSRene Gollent			TypeUnitTableEntry* entry = new(std::nothrow)
111871fec49eSRene Gollent				TypeUnitTableEntry(signature, unit);
111971fec49eSRene Gollent			if (entry == NULL)
112071fec49eSRene Gollent				return B_NO_MEMORY;
112171fec49eSRene Gollent
112271fec49eSRene Gollent			fTypeUnits.Insert(entry);
112371fec49eSRene Gollent		}
112471fec49eSRene Gollent
112571fec49eSRene Gollent		dataReader.SeekAbsolute(unitLengthOffset + unitLength);
112671fec49eSRene Gollent	}
112771fec49eSRene Gollent
112871fec49eSRene Gollent	return B_OK;
112971fec49eSRene Gollent}
113071fec49eSRene Gollent
113171fec49eSRene Gollent
1132d390ebeeSRene Gollentstatus_t
1133d390ebeeSRene GollentDwarfFile::_ParseFrameSection(ElfSection* section, uint8 addressSize,
1134d390ebeeSRene Gollent	bool ehFrame, FDEInfoList& infos)
1135d390ebeeSRene Gollent{
1136d390ebeeSRene Gollent	if (ehFrame) {
1137d390ebeeSRene Gollent		fItaniumEHFrameFormat = section->IsWritable();
1138d390ebeeSRene Gollent			// Crude heuristic for recognizing GCC 4 (Itanium ABI) style
1139d390ebeeSRene Gollent			// .eh_frame sections. The ones generated by GCC 2 are writable,
1140d390ebeeSRene Gollent			// the ones generated by GCC 4 aren't.
1141d390ebeeSRene Gollent	}
1142d390ebeeSRene Gollent
1143d390ebeeSRene Gollent	DataReader dataReader((uint8*)section->Data(),
1144d390ebeeSRene Gollent		section->Size(), addressSize);
1145d390ebeeSRene Gollent
1146d390ebeeSRene Gollent	while (dataReader.BytesRemaining() > 0) {
1147d390ebeeSRene Gollent		// length
1148d390ebeeSRene Gollent		bool dwarf64;
1149d390ebeeSRene Gollent		off_t entryOffset = dataReader.Offset();
1150d390ebeeSRene Gollent		uint64 length = dataReader.ReadInitialLength(dwarf64);
1151d390ebeeSRene Gollent
1152d390ebeeSRene Gollent		TRACE_CFI("DwarfFile::_ParseFrameSection(): offset: %" B_PRIdOFF
1153d390ebeeSRene Gollent			", length: %" B_PRId64 "\n", entryOffset, length);
1154d390ebeeSRene Gollent
1155d390ebeeSRene Gollent		if (length > (uint64)dataReader.BytesRemaining())
1156d390ebeeSRene Gollent			return B_BAD_DATA;
1157d390ebeeSRene Gollent		off_t lengthOffset = dataReader.Offset();
1158d390ebeeSRene Gollent
1159d390ebeeSRene Gollent		// CIE ID/CIE pointer
1160d390ebeeSRene Gollent		uint64 cieID = dwarf64
1161d390ebeeSRene Gollent			? dataReader.Read<uint64>(0) : dataReader.Read<uint32>(0);
1162d390ebeeSRene Gollent
1163d390ebeeSRene Gollent		// In .debug_frame ~0 indicates a CIE, in .eh_frame 0 does.
1164d390ebeeSRene Gollent		if (ehFrame
1165d390ebeeSRene Gollent			? cieID == 0
1166d390ebeeSRene Gollent			: (dwarf64
1167d390ebeeSRene Gollent				? cieID == 0xffffffffffffffffULL
1168d390ebeeSRene Gollent				: cieID == 0xffffffff)) {
1169d390ebeeSRene Gollent			// this is a CIE -- skip it
1170d390ebeeSRene Gollent		} else {
1171d390ebeeSRene Gollent			// this is a FDE
1172d390ebeeSRene Gollent			uint64 initialLocationOffset = dataReader.Offset();
1173d390ebeeSRene Gollent			// In .eh_frame the CIE offset is a relative back offset.
1174d390ebeeSRene Gollent			if (ehFrame) {
1175d390ebeeSRene Gollent				if (cieID > (uint64)lengthOffset) {
1176d390ebeeSRene Gollent					TRACE_CFI("Invalid CIE offset: %" B_PRIu64 ", max "
1177d390ebeeSRene Gollent						"possible: %" B_PRIu64 "\n", cieID, lengthOffset);
1178d390ebeeSRene Gollent					break;
1179d390ebeeSRene Gollent				}
1180d390ebeeSRene Gollent				// convert to a section relative offset
1181d390ebeeSRene Gollent				cieID = lengthOffset - cieID;
1182d390ebeeSRene Gollent			}
1183d390ebeeSRene Gollent
1184d390ebeeSRene Gollent
1185d390ebeeSRene Gollent			CfaContext context;
1186d390ebeeSRene Gollent			CIEAugmentation cieAugmentation;
1187d390ebeeSRene Gollent			// when using .eh_frame format, we need to parse the CIE's
1188d390ebeeSRene Gollent			// augmentation up front in order to know how the FDE's addresses
1189d390ebeeSRene Gollent			//  will be represented
1190d390ebeeSRene Gollent			DataReader cieReader;
1191d390ebeeSRene Gollent			off_t cieRemaining;
1192d390ebeeSRene Gollent			status_t error = _ParseCIEHeader(section, ehFrame, NULL,
1193d390ebeeSRene Gollent				addressSize, context, cieID, cieAugmentation, cieReader,
1194d390ebeeSRene Gollent				cieRemaining);
1195d390ebeeSRene Gollent			if (error != B_OK)
1196d390ebeeSRene Gollent				return error;
1197d390ebeeSRene Gollent			if (cieReader.HasOverflow())
1198d390ebeeSRene Gollent				return B_BAD_DATA;
1199d390ebeeSRene Gollent			if (cieRemaining < 0)
1200d390ebeeSRene Gollent				return B_BAD_DATA;
1201d390ebeeSRene Gollent
1202d390ebeeSRene Gollent			target_addr_t initialLocation = cieAugmentation.ReadEncodedAddress(
1203d390ebeeSRene Gollent				dataReader, fElfFile, section);
1204d390ebeeSRene Gollent			target_addr_t addressRange = cieAugmentation.ReadEncodedAddress(
1205d390ebeeSRene Gollent				dataReader, fElfFile, section, true);
1206d390ebeeSRene Gollent
1207d390ebeeSRene Gollent			if (dataReader.HasOverflow())
1208d390ebeeSRene Gollent				return B_BAD_DATA;
1209d390ebeeSRene Gollent
1210d390ebeeSRene Gollent			if ((cieAugmentation.FDEAddressType()
1211d390ebeeSRene Gollent					& CFI_ADDRESS_TYPE_PC_RELATIVE) != 0) {
1212d390ebeeSRene Gollent				initialLocation += initialLocationOffset;
1213d390ebeeSRene Gollent			}
1214d390ebeeSRene Gollent
1215d390ebeeSRene Gollent			// for unknown reasons, the debug frame sections generated by gcc
1216d390ebeeSRene Gollent			// sometimes contain duplicates at different offsets within the
1217d390ebeeSRene Gollent			// section. In such a case, simply skip the duplicates.
1218d390ebeeSRene Gollent			FDELookupInfo* temp = _GetContainingFDEInfo(initialLocation,
1219d390ebeeSRene Gollent				infos);
1220d390ebeeSRene Gollent			if (temp == NULL) {
1221d390ebeeSRene Gollent				FDELookupInfo* info = new(std::nothrow)FDELookupInfo(
1222d390ebeeSRene Gollent					initialLocation, initialLocation + addressRange - 1,
1223d390ebeeSRene Gollent					entryOffset, cieID, ehFrame);
1224d390ebeeSRene Gollent				if (info == NULL)
1225d390ebeeSRene Gollent					return B_NO_MEMORY;
1226d390ebeeSRene Gollent
1227d390ebeeSRene Gollent				ObjectDeleter<FDELookupInfo> infoDeleter(info);
1228d390ebeeSRene Gollent				if (!infos.BinaryInsert(info, FDELookupInfo::CompareFDEInfos))
1229d390ebeeSRene Gollent					return B_NO_MEMORY;
1230d390ebeeSRene Gollent
1231d390ebeeSRene Gollent				infoDeleter.Detach();
1232d390ebeeSRene Gollent			}
1233d390ebeeSRene Gollent		}
1234d390ebeeSRene Gollent
1235d390ebeeSRene Gollent		dataReader.SeekAbsolute(lengthOffset + length);
1236d390ebeeSRene Gollent	}
1237d390ebeeSRene Gollent
1238d390ebeeSRene Gollent	return B_OK;
1239d390ebeeSRene Gollent}
1240d390ebeeSRene Gollent
1241d390ebeeSRene Gollent
12427a7112b3SIngo Weinholdstatus_t
12437a7112b3SIngo WeinholdDwarfFile::_ParseCompilationUnit(CompilationUnit* unit)
12447a7112b3SIngo Weinhold{
12457a7112b3SIngo Weinhold	AbbreviationTable* abbreviationTable;
12467a7112b3SIngo Weinhold	status_t error = _GetAbbreviationTable(unit->AbbreviationOffset(),
12477a7112b3SIngo Weinhold		abbreviationTable);
12487a7112b3SIngo Weinhold	if (error != B_OK)
12497a7112b3SIngo Weinhold		return error;
12507a7112b3SIngo Weinhold
12517a7112b3SIngo Weinhold	unit->SetAbbreviationTable(abbreviationTable);
12527a7112b3SIngo Weinhold
12537a7112b3SIngo Weinhold	DataReader dataReader(
12547a7112b3SIngo Weinhold		(const uint8*)fDebugInfoSection->Data() + unit->ContentOffset(),
1255106c4d40SIngo Weinhold		unit->ContentSize(), unit->AddressSize());
12567a7112b3SIngo Weinhold
12577a7112b3SIngo Weinhold	DebugInfoEntry* entry;
12587a7112b3SIngo Weinhold	bool endOfEntryList;
125971fec49eSRene Gollent	error = _ParseDebugInfoEntry(dataReader, unit, abbreviationTable, entry,
12607a7112b3SIngo Weinhold		endOfEntryList);
12617a7112b3SIngo Weinhold	if (error != B_OK)
12627a7112b3SIngo Weinhold		return error;
12637a7112b3SIngo Weinhold
12647c3612f4SIngo Weinhold	DIECompileUnitBase* unitEntry = dynamic_cast<DIECompileUnitBase*>(entry);
12657c3612f4SIngo Weinhold	if (unitEntry == NULL) {
12666e72ebfcSIngo Weinhold		WARNING("No compilation unit entry in .debug_info section.\n");
12677a7112b3SIngo Weinhold		return B_BAD_DATA;
12687a7112b3SIngo Weinhold	}
12697a7112b3SIngo Weinhold
12707c3612f4SIngo Weinhold	unit->SetUnitEntry(unitEntry);
12717c3612f4SIngo Weinhold
12726e72ebfcSIngo Weinhold	TRACE_DIE_ONLY(
12737483c98dSIngo Weinhold		TRACE_DIE("remaining bytes in unit: %" B_PRIdOFF "\n",
12746e72ebfcSIngo Weinhold			dataReader.BytesRemaining());
12756e72ebfcSIngo Weinhold		if (dataReader.HasData()) {
12766e72ebfcSIngo Weinhold			TRACE_DIE("  ");
12776e72ebfcSIngo Weinhold			while (dataReader.HasData())
12786e72ebfcSIngo Weinhold				TRACE_DIE("%02x", dataReader.Read<uint8>(0));
12796e72ebfcSIngo Weinhold			TRACE_DIE("\n");
12806e72ebfcSIngo Weinhold		}
12816e72ebfcSIngo Weinhold	)
12827a7112b3SIngo Weinhold	return B_OK;
12837a7112b3SIngo Weinhold}
12847a7112b3SIngo Weinhold
12857a7112b3SIngo Weinhold
128671fec49eSRene Gollentstatus_t
128771fec49eSRene GollentDwarfFile::_ParseTypeUnit(TypeUnit* unit)
128871fec49eSRene Gollent{
128971fec49eSRene Gollent	AbbreviationTable* abbreviationTable;
129071fec49eSRene Gollent	status_t error = _GetAbbreviationTable(unit->AbbreviationOffset(),
129171fec49eSRene Gollent		abbreviationTable);
129271fec49eSRene Gollent	if (error != B_OK)
129371fec49eSRene Gollent		return error;
129471fec49eSRene Gollent
129571fec49eSRene Gollent	unit->SetAbbreviationTable(abbreviationTable);
129671fec49eSRene Gollent
129771fec49eSRene Gollent	DataReader dataReader(
129871fec49eSRene Gollent		(const uint8*)fDebugTypesSection->Data() + unit->ContentOffset(),
129971fec49eSRene Gollent		unit->ContentSize(), unit->AddressSize());
130071fec49eSRene Gollent
130171fec49eSRene Gollent	DebugInfoEntry* entry;
130271fec49eSRene Gollent	bool endOfEntryList;
130371fec49eSRene Gollent	error = _ParseDebugInfoEntry(dataReader, unit, abbreviationTable, entry,
130471fec49eSRene Gollent		endOfEntryList);
130571fec49eSRene Gollent	if (error != B_OK)
130671fec49eSRene Gollent		return error;
130771fec49eSRene Gollent
130871fec49eSRene Gollent	DIETypeUnit* unitEntry = dynamic_cast<DIETypeUnit*>(entry);
130971fec49eSRene Gollent	if (unitEntry == NULL) {
131071fec49eSRene Gollent		WARNING("No type unit entry in .debug_types section.\n");
131171fec49eSRene Gollent		return B_BAD_DATA;
131271fec49eSRene Gollent	}
131371fec49eSRene Gollent
131471fec49eSRene Gollent	unit->SetUnitEntry(unitEntry);
1315104b2886SRene Gollent	DebugInfoEntry* typeEntry = unit->EntryForOffset(unit->TypeOffset());
1316104b2886SRene Gollent	if (typeEntry == NULL) {
1317104b2886SRene Gollent		WARNING("No type found for type unit %p at specified offset %"
1318104b2886SRene Gollent			B_PRId64 ".\n", unit, unit->TypeOffset());
1319104b2886SRene Gollent		return B_BAD_DATA;
1320104b2886SRene Gollent	}
1321104b2886SRene Gollent	unit->SetTypeEntry(typeEntry);
132271fec49eSRene Gollent
132371fec49eSRene Gollent	TRACE_DIE_ONLY(
132471fec49eSRene Gollent		TRACE_DIE("remaining bytes in unit: %" B_PRIdOFF "\n",
132571fec49eSRene Gollent			dataReader.BytesRemaining());
132671fec49eSRene Gollent		if (dataReader.HasData()) {
132771fec49eSRene Gollent			TRACE_DIE("  ");
132871fec49eSRene Gollent			while (dataReader.HasData())
132971fec49eSRene Gollent				TRACE_DIE("%02x", dataReader.Read<uint8>(0));
133071fec49eSRene Gollent			TRACE_DIE("\n");
133171fec49eSRene Gollent		}
133271fec49eSRene Gollent	)
133371fec49eSRene Gollent	return B_OK;
133471fec49eSRene Gollent}
133571fec49eSRene Gollent
133671fec49eSRene Gollent
13377a7112b3SIngo Weinholdstatus_t
13387a7112b3SIngo WeinholdDwarfFile::_ParseDebugInfoEntry(DataReader& dataReader,
133971fec49eSRene Gollent	BaseUnit* unit, AbbreviationTable* abbreviationTable,
134071fec49eSRene Gollent	DebugInfoEntry*& _entry, bool& _endOfEntryList, int level)
13417a7112b3SIngo Weinhold{
1342106c4d40SIngo Weinhold	off_t entryOffset = dataReader.Offset()
134371fec49eSRene Gollent		+ unit->RelativeContentOffset();
13447a7112b3SIngo Weinhold
13457a7112b3SIngo Weinhold	uint32 code = dataReader.ReadUnsignedLEB128(0);
13467a7112b3SIngo Weinhold	if (code == 0) {
13477a7112b3SIngo Weinhold		if (dataReader.HasOverflow()) {
13486e72ebfcSIngo Weinhold			WARNING("Unexpected end of .debug_info section.\n");
13497a7112b3SIngo Weinhold			return B_BAD_DATA;
13507a7112b3SIngo Weinhold		}
13517a7112b3SIngo Weinhold		_entry = NULL;
13527a7112b3SIngo Weinhold		_endOfEntryList = true;
13537a7112b3SIngo Weinhold		return B_OK;
13547a7112b3SIngo Weinhold	}
13557a7112b3SIngo Weinhold
13567a7112b3SIngo Weinhold	// get the corresponding abbreviation entry
13577a7112b3SIngo Weinhold	AbbreviationEntry abbreviationEntry;
13587a7112b3SIngo Weinhold	if (!abbreviationTable->GetAbbreviationEntry(code, abbreviationEntry)) {
135971fec49eSRene Gollent		WARNING("No abbreviation entry for code %" B_PRIx32 "\n", code);
13607a7112b3SIngo Weinhold		return B_BAD_DATA;
13617a7112b3SIngo Weinhold	}
13627a7112b3SIngo Weinhold
13637a7112b3SIngo Weinhold	DebugInfoEntry* entry;
13647a7112b3SIngo Weinhold	status_t error = fDebugInfoFactory.CreateDebugInfoEntry(
13657a7112b3SIngo Weinhold		abbreviationEntry.Tag(), entry);
13666faa3c97SRene Gollent	if (error != B_OK) {
13677483c98dSIngo Weinhold		WARNING("Failed to generate entry for tag %" B_PRIu32 ", code %"
13687483c98dSIngo Weinhold			B_PRIu32 "\n", abbreviationEntry.Tag(), code);
13697a7112b3SIngo Weinhold		return error;
13706faa3c97SRene Gollent	}
13716faa3c97SRene Gollent
13727a7112b3SIngo Weinhold	ObjectDeleter<DebugInfoEntry> entryDeleter(entry);
13737a7112b3SIngo Weinhold
13747483c98dSIngo Weinhold	TRACE_DIE("%*sentry %p at %" B_PRIdOFF ": %" B_PRIu32 ", tag: %s (%"
13757483c98dSIngo Weinhold		B_PRIu32 "), children: %d\n", level * 2, "", entry, entryOffset,
13767483c98dSIngo Weinhold		abbreviationEntry.Code(), get_entry_tag_name(abbreviationEntry.Tag()),
13777483c98dSIngo Weinhold		abbreviationEntry.Tag(), abbreviationEntry.HasChildren());
13786e72ebfcSIngo Weinhold
137971fec49eSRene Gollent	error = unit->AddDebugInfoEntry(entry, entryOffset);
138071fec49eSRene Gollent
13817a7112b3SIngo Weinhold	if (error != B_OK)
13827a7112b3SIngo Weinhold		return error;
13837a7112b3SIngo Weinhold
13847a7112b3SIngo Weinhold	// parse the attributes (supply NULL entry to avoid adding them yet)
138571fec49eSRene Gollent	error = _ParseEntryAttributes(dataReader, unit, NULL, abbreviationEntry);
13867a7112b3SIngo Weinhold	if (error != B_OK)
13877a7112b3SIngo Weinhold		return error;
13887a7112b3SIngo Weinhold
13897a7112b3SIngo Weinhold	// parse children, if the entry has any
13907a7112b3SIngo Weinhold	if (abbreviationEntry.HasChildren()) {
13917a7112b3SIngo Weinhold		while (true) {
13927a7112b3SIngo Weinhold			DebugInfoEntry* childEntry;
13937a7112b3SIngo Weinhold			bool endOfEntryList;
13947a7112b3SIngo Weinhold			status_t error = _ParseDebugInfoEntry(dataReader,
139571fec49eSRene Gollent				unit, abbreviationTable, childEntry, endOfEntryList, level + 1);
13967a7112b3SIngo Weinhold			if (error != B_OK)
13977a7112b3SIngo Weinhold				return error;
13987a7112b3SIngo Weinhold
13997a7112b3SIngo Weinhold			// add the child to our entry
14007a7112b3SIngo Weinhold			if (childEntry != NULL) {
14017a7112b3SIngo Weinhold				if (entry != NULL) {
14027a7112b3SIngo Weinhold					error = entry->AddChild(childEntry);
14035b60969cSIngo Weinhold					if (error == B_OK) {
14045b60969cSIngo Weinhold						childEntry->SetParent(entry);
14055b60969cSIngo Weinhold					} else if (error == ENTRY_NOT_HANDLED) {
14067a7112b3SIngo Weinhold						error = B_OK;
14076e72ebfcSIngo Weinhold						TRACE_DIE("%*s  -> child unhandled\n", level * 2, "");
14087a7112b3SIngo Weinhold					}
14097a7112b3SIngo Weinhold
14107a7112b3SIngo Weinhold					if (error != B_OK) {
14117a7112b3SIngo Weinhold						delete childEntry;
14127a7112b3SIngo Weinhold						return error;
14137a7112b3SIngo Weinhold					}
14147a7112b3SIngo Weinhold				} else
14157a7112b3SIngo Weinhold					delete childEntry;
14167a7112b3SIngo Weinhold			}
14177a7112b3SIngo Weinhold
14187a7112b3SIngo Weinhold			if (endOfEntryList)
14197a7112b3SIngo Weinhold				break;
14207a7112b3SIngo Weinhold		}
14217a7112b3SIngo Weinhold	}
14227a7112b3SIngo Weinhold
14237a7112b3SIngo Weinhold	entryDeleter.Detach();
14247a7112b3SIngo Weinhold	_entry = entry;
14257a7112b3SIngo Weinhold	_endOfEntryList = false;
14267a7112b3SIngo Weinhold	return B_OK;
14277a7112b3SIngo Weinhold}
14287a7112b3SIngo Weinhold
14297a7112b3SIngo Weinhold
14307a7112b3SIngo Weinholdstatus_t
143171fec49eSRene GollentDwarfFile::_FinishUnit(BaseUnit* unit)
14327a7112b3SIngo Weinhold{
143371fec49eSRene Gollent	CompilationUnit* compilationUnit = dynamic_cast<CompilationUnit*>(unit);
143471fec49eSRene Gollent	bool isTypeUnit = compilationUnit == NULL;
143571fec49eSRene Gollent	TRACE_DIE("\nfinishing %s unit %p\n",
143671fec49eSRene Gollent		isTypeUnit ? "type" : "compilation", unit);
143771fec49eSRene Gollent
14386e72ebfcSIngo Weinhold
14397a7112b3SIngo Weinhold	AbbreviationTable* abbreviationTable = unit->GetAbbreviationTable();
14407a7112b3SIngo Weinhold
144171fec49eSRene Gollent	ElfSection* section = isTypeUnit
144271fec49eSRene Gollent			? fDebugTypesSection : fDebugInfoSection;
14437a7112b3SIngo Weinhold	DataReader dataReader(
144471fec49eSRene Gollent		(const uint8*)section->Data() + unit->HeaderOffset(),
1445106c4d40SIngo Weinhold		unit->TotalSize(), unit->AddressSize());
14467a7112b3SIngo Weinhold
14477a7112b3SIngo Weinhold	DebugInfoEntryInitInfo entryInitInfo;
14487a7112b3SIngo Weinhold
14497a7112b3SIngo Weinhold	int entryCount = unit->CountEntries();
14507a7112b3SIngo Weinhold	for (int i = 0; i < entryCount; i++) {
14517a7112b3SIngo Weinhold		// get the entry
14527a7112b3SIngo Weinhold		DebugInfoEntry* entry;
1453106c4d40SIngo Weinhold		off_t offset;
14547a7112b3SIngo Weinhold		unit->GetEntryAt(i, entry, offset);
14556e72ebfcSIngo Weinhold
14567483c98dSIngo Weinhold		TRACE_DIE("entry %p at %" B_PRIdOFF "\n", entry, offset);
14577a7112b3SIngo Weinhold
14587a7112b3SIngo Weinhold		// seek the reader to the entry
14597a7112b3SIngo Weinhold		dataReader.SeekAbsolute(offset);
14607a7112b3SIngo Weinhold
14617a7112b3SIngo Weinhold		// read the entry code
14627a7112b3SIngo Weinhold		uint32 code = dataReader.ReadUnsignedLEB128(0);
14637a7112b3SIngo Weinhold
14647a7112b3SIngo Weinhold		// get the respective abbreviation entry
14657a7112b3SIngo Weinhold		AbbreviationEntry abbreviationEntry;
14667a7112b3SIngo Weinhold		abbreviationTable->GetAbbreviationEntry(code, abbreviationEntry);
14677a7112b3SIngo Weinhold
14687a7112b3SIngo Weinhold		// initialization before setting the attributes
14697a7112b3SIngo Weinhold		status_t error = entry->InitAfterHierarchy(entryInitInfo);
14707a7112b3SIngo Weinhold		if (error != B_OK) {
14716e72ebfcSIngo Weinhold			WARNING("Init after hierarchy failed!\n");
14727a7112b3SIngo Weinhold			return error;
14737a7112b3SIngo Weinhold		}
14747a7112b3SIngo Weinhold
14757a7112b3SIngo Weinhold		// parse the attributes -- this time pass the entry, so that the
14767a7112b3SIngo Weinhold		// attribute get set on it
147771fec49eSRene Gollent		error = _ParseEntryAttributes(dataReader, unit, entry,
147871fec49eSRene Gollent			abbreviationEntry);
14797a7112b3SIngo Weinhold		if (error != B_OK)
14807a7112b3SIngo Weinhold			return error;
14817a7112b3SIngo Weinhold
14827a7112b3SIngo Weinhold		// initialization after setting the attributes
14837a7112b3SIngo Weinhold		error = entry->InitAfterAttributes(entryInitInfo);
14847a7112b3SIngo Weinhold		if (error != B_OK) {
14856e72ebfcSIngo Weinhold			WARNING("Init after attributes failed!\n");
14867a7112b3SIngo Weinhold			return error;
14877a7112b3SIngo Weinhold		}
14887a7112b3SIngo Weinhold	}
14897a7112b3SIngo Weinhold
14907d82c6ddSIngo Weinhold	// set the compilation unit's source language
14917d82c6ddSIngo Weinhold	unit->SetSourceLanguage(entryInitInfo.languageInfo);
14927d82c6ddSIngo Weinhold
149371fec49eSRene Gollent	if (isTypeUnit)
149471fec49eSRene Gollent		return B_OK;
149571fec49eSRene Gollent
14963c33a74cSIngo Weinhold	// resolve the compilation unit's address range list
149771fec49eSRene Gollent	if (TargetAddressRangeList* ranges = ResolveRangeList(compilationUnit,
149871fec49eSRene Gollent			compilationUnit->UnitEntry()->AddressRangesOffset())) {
149971fec49eSRene Gollent		compilationUnit->SetAddressRanges(ranges);
15003c33a74cSIngo Weinhold		ranges->ReleaseReference();
15013c33a74cSIngo Weinhold	}
15023c33a74cSIngo Weinhold
15037413cddeSIngo Weinhold	// add compilation dir to directory list
150471fec49eSRene Gollent	const char* compilationDir = compilationUnit->UnitEntry()
150571fec49eSRene Gollent		->CompilationDir();
150671fec49eSRene Gollent	if (!compilationUnit->AddDirectory(compilationDir != NULL
150771fec49eSRene Gollent				? compilationDir : ".")) {
15087413cddeSIngo Weinhold		return B_NO_MEMORY;
150971fec49eSRene Gollent	}
15107413cddeSIngo Weinhold
15117413cddeSIngo Weinhold	// parse line info header
151291c6759fSIngo Weinhold	if (fDebugLineSection != NULL)
151371fec49eSRene Gollent		_ParseLineInfo(compilationUnit);
151491c6759fSIngo Weinhold
15157a7112b3SIngo Weinhold	return B_OK;
15167a7112b3SIngo Weinhold}
15177a7112b3SIngo Weinhold
15187a7112b3SIngo Weinhold
15197a7112b3SIngo Weinholdstatus_t
15207a7112b3SIngo WeinholdDwarfFile::_ParseEntryAttributes(DataReader& dataReader,
152171fec49eSRene Gollent	BaseUnit* unit, DebugInfoEntry* entry, AbbreviationEntry& abbreviationEntry)
15227a7112b3SIngo Weinhold{
15237a7112b3SIngo Weinhold	uint32 attributeName;
15247a7112b3SIngo Weinhold	uint32 attributeForm;
15257a7112b3SIngo Weinhold	while (abbreviationEntry.GetNextAttribute(attributeName,
15267a7112b3SIngo Weinhold			attributeForm)) {
15277a7112b3SIngo Weinhold		// resolve attribute form indirection
15287a7112b3SIngo Weinhold		if (attributeForm == DW_FORM_indirect)
15297a7112b3SIngo Weinhold			attributeForm = dataReader.ReadUnsignedLEB128(0);
15307a7112b3SIngo Weinhold
15317a7112b3SIngo Weinhold		// prepare an AttributeValue
15327a7112b3SIngo Weinhold		AttributeValue attributeValue;
15337a7112b3SIngo Weinhold		attributeValue.attributeForm = attributeForm;
15345b60969cSIngo Weinhold		bool isSigned = false;
15357a7112b3SIngo Weinhold
15367a7112b3SIngo Weinhold		// Read the attribute value according to the attribute's form. For
15377a7112b3SIngo Weinhold		// the forms that don't map to a single attribute class only or
15387a7112b3SIngo Weinhold		// those that need additional processing, we read a temporary value
15397a7112b3SIngo Weinhold		// first.
15407a7112b3SIngo Weinhold		uint64 value = 0;
1541106c4d40SIngo Weinhold		off_t blockLength = 0;
154271fec49eSRene Gollent		off_t valueOffset = dataReader.Offset() + unit->ContentOffset();
154371fec49eSRene Gollent		uint8 refType = dwarf_reference_type_local;
15447a7112b3SIngo Weinhold
15457a7112b3SIngo Weinhold		switch (attributeForm) {
15467a7112b3SIngo Weinhold			case DW_FORM_addr:
1547106c4d40SIngo Weinhold				value = dataReader.ReadAddress(0);
15487a7112b3SIngo Weinhold				break;
15497a7112b3SIngo Weinhold			case DW_FORM_block2:
15507a7112b3SIngo Weinhold				blockLength = dataReader.Read<uint16>(0);
15517a7112b3SIngo Weinhold				break;
15527a7112b3SIngo Weinhold			case DW_FORM_block4:
15537a7112b3SIngo Weinhold				blockLength = dataReader.Read<uint32>(0);
15547a7112b3SIngo Weinhold				break;
15557a7112b3SIngo Weinhold			case DW_FORM_data2:
15567a7112b3SIngo Weinhold				value = dataReader.Read<uint16>(0);
15577a7112b3SIngo Weinhold				break;
15587a7112b3SIngo Weinhold			case DW_FORM_data4:
15597a7112b3SIngo Weinhold				value = dataReader.Read<uint32>(0);
15607a7112b3SIngo Weinhold				break;
15617a7112b3SIngo Weinhold			case DW_FORM_data8:
15627a7112b3SIngo Weinhold				value = dataReader.Read<uint64>(0);
15637a7112b3SIngo Weinhold				break;
15647a7112b3SIngo Weinhold			case DW_FORM_string:
15655b60969cSIngo Weinhold				attributeValue.SetToString(dataReader.ReadString());
15667a7112b3SIngo Weinhold				break;
15677a7112b3SIngo Weinhold			case DW_FORM_block:
15686882d4b5SRene Gollent			case DW_FORM_exprloc:
15697a7112b3SIngo Weinhold				blockLength = dataReader.ReadUnsignedLEB128(0);
15707a7112b3SIngo Weinhold				break;
15717a7112b3SIngo Weinhold			case DW_FORM_block1:
15727a7112b3SIngo Weinhold				blockLength = dataReader.Read<uint8>(0);
15737a7112b3SIngo Weinhold				break;
15747a7112b3SIngo Weinhold			case DW_FORM_data1:
15757a7112b3SIngo Weinhold				value = dataReader.Read<uint8>(0);
15767a7112b3SIngo Weinhold				break;
15777a7112b3SIngo Weinhold			case DW_FORM_flag:
15785b60969cSIngo Weinhold				attributeValue.SetToFlag(dataReader.Read<uint8>(0) != 0);
15797a7112b3SIngo Weinhold				break;
15807a7112b3SIngo Weinhold			case DW_FORM_sdata:
15817a7112b3SIngo Weinhold				value = dataReader.ReadSignedLEB128(0);
15825b60969cSIngo Weinhold				isSigned = true;
15837a7112b3SIngo Weinhold				break;
15847a7112b3SIngo Weinhold			case DW_FORM_strp:
15857a7112b3SIngo Weinhold			{
1586c93db3c1SIngo Weinhold				if (fDebugStringSection != NULL) {
158705c7cd76SIngo Weinhold					uint64 offset = unit->IsDwarf64()
158805c7cd76SIngo Weinhold						? dataReader.Read<uint64>(0)
158905c7cd76SIngo Weinhold						: dataReader.Read<uint32>(0);
1590c93db3c1SIngo Weinhold					if (offset >= fDebugStringSection->Size()) {
159105c7cd76SIngo Weinhold						WARNING("Invalid DW_FORM_strp offset: %" B_PRIu64 "\n",
15927483c98dSIngo Weinhold							offset);
1593c93db3c1SIngo Weinhold						return B_BAD_DATA;
1594c93db3c1SIngo Weinhold					}
1595c93db3c1SIngo Weinhold					attributeValue.SetToString(
1596c93db3c1SIngo Weinhold						(const char*)fDebugStringSection->Data() + offset);
1597c93db3c1SIngo Weinhold				} else {
15986e72ebfcSIngo Weinhold					WARNING("Invalid DW_FORM_strp: no string section!\n");
15997a7112b3SIngo Weinhold					return B_BAD_DATA;
16007a7112b3SIngo Weinhold				}
16017a7112b3SIngo Weinhold				break;
16027a7112b3SIngo Weinhold			}
16037a7112b3SIngo Weinhold			case DW_FORM_udata:
16047a7112b3SIngo Weinhold				value = dataReader.ReadUnsignedLEB128(0);
16057a7112b3SIngo Weinhold				break;
16067a7112b3SIngo Weinhold			case DW_FORM_ref_addr:
160771fec49eSRene Gollent				value = unit->IsDwarf64()
1608106c4d40SIngo Weinhold					? dataReader.Read<uint64>(0)
1609106c4d40SIngo Weinhold					: (uint64)dataReader.Read<uint32>(0);
161071fec49eSRene Gollent				refType = dwarf_reference_type_global;
16117a7112b3SIngo Weinhold				break;
16127a7112b3SIngo Weinhold			case DW_FORM_ref1:
16137a7112b3SIngo Weinhold				value = dataReader.Read<uint8>(0);
16147a7112b3SIngo Weinhold				break;
16157a7112b3SIngo Weinhold			case DW_FORM_ref2:
16167a7112b3SIngo Weinhold				value = dataReader.Read<uint16>(0);
16177a7112b3SIngo Weinhold				break;
16187a7112b3SIngo Weinhold			case DW_FORM_ref4:
16197a7112b3SIngo Weinhold				value = dataReader.Read<uint32>(0);
16207a7112b3SIngo Weinhold				break;
16217a7112b3SIngo Weinhold			case DW_FORM_ref8:
16227a7112b3SIngo Weinhold				value = dataReader.Read<uint64>(0);
16237a7112b3SIngo Weinhold				break;
16247a7112b3SIngo Weinhold			case DW_FORM_ref_udata:
16257a7112b3SIngo Weinhold				value = dataReader.ReadUnsignedLEB128(0);
16267a7112b3SIngo Weinhold				break;
16272f6ecd57SRene Gollent			case DW_FORM_flag_present:
1628a074f354SRene Gollent				attributeValue.SetToFlag(true);
16292f6ecd57SRene Gollent				break;
16302f6ecd57SRene Gollent			case DW_FORM_ref_sig8:
163171fec49eSRene Gollent				fTypesSectionRequired = true;
16322f6ecd57SRene Gollent				value = dataReader.Read<uint64>(0);
163371fec49eSRene Gollent				refType = dwarf_reference_type_signature;
16342f6ecd57SRene Gollent				break;
16352f6ecd57SRene Gollent			case DW_FORM_sec_offset:
163671fec49eSRene Gollent				value = unit->IsDwarf64()
1637db935bfbSRene Gollent					? dataReader.Read<uint64>(0)
1638db935bfbSRene Gollent					: (uint64)dataReader.Read<uint32>(0);
1639db935bfbSRene Gollent				break;
1640db935bfbSRene Gollent			case DW_FORM_indirect:
16417a7112b3SIngo Weinhold			default:
16427483c98dSIngo Weinhold				WARNING("Unsupported attribute form: %" B_PRIu32 "\n",
16437483c98dSIngo Weinhold					attributeForm);
16447a7112b3SIngo Weinhold				return B_BAD_DATA;
16457a7112b3SIngo Weinhold		}
16467a7112b3SIngo Weinhold
16477a7112b3SIngo Weinhold		// get the attribute class -- skip the attribute, if we can't handle
16487a7112b3SIngo Weinhold		// it
16497a7112b3SIngo Weinhold		uint8 attributeClass = get_attribute_class(attributeName,
16507a7112b3SIngo Weinhold			attributeForm);
165171fec49eSRene Gollent
16527a7112b3SIngo Weinhold		if (attributeClass == ATTRIBUTE_CLASS_UNKNOWN) {
16537483c98dSIngo Weinhold			TRACE_DIE("skipping attribute with unrecognized class: %s (%#"
16547483c98dSIngo Weinhold				B_PRIx32 ") %s (%#" B_PRIx32 ")\n",
16557483c98dSIngo Weinhold				get_attribute_name_name(attributeName), attributeName,
16567483c98dSIngo Weinhold				get_attribute_form_name(attributeForm), attributeForm);
1657428bbe89SRene Gollent			continue;
16587a7112b3SIngo Weinhold		}
16597a7112b3SIngo Weinhold
16607a7112b3SIngo Weinhold		// set the attribute value according to the attribute's class
16617a7112b3SIngo Weinhold		switch (attributeClass) {
16627a7112b3SIngo Weinhold			case ATTRIBUTE_CLASS_ADDRESS:
16635b60969cSIngo Weinhold				attributeValue.SetToAddress(value);
16647a7112b3SIngo Weinhold				break;
16657a7112b3SIngo Weinhold			case ATTRIBUTE_CLASS_BLOCK:
16665b60969cSIngo Weinhold				attributeValue.SetToBlock(dataReader.Data(), blockLength);
16677a7112b3SIngo Weinhold				dataReader.Skip(blockLength);
16687a7112b3SIngo Weinhold				break;
16697a7112b3SIngo Weinhold			case ATTRIBUTE_CLASS_CONSTANT:
16705b60969cSIngo Weinhold				attributeValue.SetToConstant(value, isSigned);
16717a7112b3SIngo Weinhold				break;
16727a7112b3SIngo Weinhold			case ATTRIBUTE_CLASS_LINEPTR:
16735b60969cSIngo Weinhold				attributeValue.SetToLinePointer(value);
16745b60969cSIngo Weinhold				break;
16757a7112b3SIngo Weinhold			case ATTRIBUTE_CLASS_LOCLISTPTR:
16765b60969cSIngo Weinhold				attributeValue.SetToLocationListPointer(value);
16775b60969cSIngo Weinhold				break;
16787a7112b3SIngo Weinhold			case ATTRIBUTE_CLASS_MACPTR:
16795b60969cSIngo Weinhold				attributeValue.SetToMacroPointer(value);
16805b60969cSIngo Weinhold				break;
16817a7112b3SIngo Weinhold			case ATTRIBUTE_CLASS_RANGELISTPTR:
16823c33a74cSIngo Weinhold				attributeValue.SetToRangeListPointer(value);
16837a7112b3SIngo Weinhold				break;
16847a7112b3SIngo Weinhold			case ATTRIBUTE_CLASS_REFERENCE:
16857a7112b3SIngo Weinhold				if (entry != NULL) {
1686d315bfd5SIngo Weinhold					attributeValue.SetToReference(_ResolveReference(
168771fec49eSRene Gollent						unit, value, refType));
16887a7112b3SIngo Weinhold					if (attributeValue.reference == NULL) {
16898a07918fSIngo Weinhold						// gcc 2 apparently somtimes produces DW_AT_sibling
16908a07918fSIngo Weinhold						// attributes pointing to the end of the sibling list.
16918a07918fSIngo Weinhold						// Just ignore those.
16928a07918fSIngo Weinhold						if (attributeName == DW_AT_sibling)
16938a07918fSIngo Weinhold							continue;
16948a07918fSIngo Weinhold
169571fec49eSRene Gollent						WARNING("Failed to resolve reference on entry %p: "
169671fec49eSRene Gollent							"(%#" B_PRIx64 ") %s (%#" B_PRIx32 ") %s "
169771fec49eSRene Gollent							"(%#" B_PRIx32 "): value: %#" B_PRIx64 "\n",
169871fec49eSRene Gollent							entry,
169971fec49eSRene Gollent							valueOffset,
17006e72ebfcSIngo Weinhold							get_attribute_name_name(attributeName),
17016e72ebfcSIngo Weinhold							attributeName,
17026e72ebfcSIngo Weinhold							get_attribute_form_name(attributeForm),
17036e72ebfcSIngo Weinhold							attributeForm, value);
17047a7112b3SIngo Weinhold						return B_ENTRY_NOT_FOUND;
17057a7112b3SIngo Weinhold					}
17067a7112b3SIngo Weinhold				}
17077a7112b3SIngo Weinhold				break;
17087a7112b3SIngo Weinhold			case ATTRIBUTE_CLASS_FLAG:
17097a7112b3SIngo Weinhold			case ATTRIBUTE_CLASS_STRING:
17107a7112b3SIngo Weinhold				// already set
17117a7112b3SIngo Weinhold				break;
17127a7112b3SIngo Weinhold		}
17137a7112b3SIngo Weinhold
17147a7112b3SIngo Weinhold		if (dataReader.HasOverflow()) {
17156e72ebfcSIngo Weinhold			WARNING("Unexpected end of .debug_info section.\n");
17167a7112b3SIngo Weinhold			return B_BAD_DATA;
17177a7112b3SIngo Weinhold		}
17187a7112b3SIngo Weinhold
171971fec49eSRene Gollent		TRACE_DIE_ONLY(
172071fec49eSRene Gollent			char buffer[1024];
172171fec49eSRene Gollent			TRACE_DIE("  attr (%#" B_PRIx64 ") %s %s (%d): %s\n",
172271fec49eSRene Gollent				valueOffset,
172371fec49eSRene Gollent				get_attribute_name_name(attributeName),
172471fec49eSRene Gollent				get_attribute_form_name(attributeForm), attributeClass,
172571fec49eSRene Gollent				attributeValue.ToString(buffer, sizeof(buffer)));
172671fec49eSRene Gollent		)
172771fec49eSRene Gollent
17287a7112b3SIngo Weinhold		// add the attribute
17297a7112b3SIngo Weinhold		if (entry != NULL) {
17307a7112b3SIngo Weinhold			DebugInfoEntrySetter attributeSetter
17317a7112b3SIngo Weinhold				= get_attribute_name_setter(attributeName);
17325b60969cSIngo Weinhold			if (attributeSetter != 0) {
17337a7112b3SIngo Weinhold				status_t error = (entry->*attributeSetter)(attributeName,
17347a7112b3SIngo Weinhold					attributeValue);
17357a7112b3SIngo Weinhold
17367a7112b3SIngo Weinhold				if (error == ATTRIBUTE_NOT_HANDLED) {
17377a7112b3SIngo Weinhold					error = B_OK;
17386e72ebfcSIngo Weinhold					TRACE_DIE("    -> unhandled\n");
17397a7112b3SIngo Weinhold				}
17407a7112b3SIngo Weinhold
17417a7112b3SIngo Weinhold				if (error != B_OK) {
17426e72ebfcSIngo Weinhold					WARNING("Failed to set attribute: name: %s, form: %s: %s\n",
17437a7112b3SIngo Weinhold						get_attribute_name_name(attributeName),
17447a7112b3SIngo Weinhold						get_attribute_form_name(attributeForm),
17457a7112b3SIngo Weinhold						strerror(error));
17467a7112b3SIngo Weinhold				}
17476e72ebfcSIngo Weinhold			} else
17486e72ebfcSIngo Weinhold				TRACE_DIE("    -> no attribute setter!\n");
17497a7112b3SIngo Weinhold		}
17507a7112b3SIngo Weinhold	}
17517a7112b3SIngo Weinhold
17527a7112b3SIngo Weinhold	return B_OK;
17537a7112b3SIngo Weinhold}
17547a7112b3SIngo Weinhold
17557a7112b3SIngo Weinhold
1756c4120026SRene Gollentstatus_t
1757c4120026SRene GollentDwarfFile::_ParseLineInfo(CompilationUnit* unit)
1758c4120026SRene Gollent{
1759c4120026SRene Gollent	off_t offset = unit->UnitEntry()->StatementListOffset();
1760c4120026SRene Gollent
17617483c98dSIngo Weinhold	TRACE_LINES("DwarfFile::_ParseLineInfo(%p), offset: %" B_PRIdOFF "\n", unit,
17627483c98dSIngo Weinhold		offset);
1763c4120026SRene Gollent
1764c4120026SRene Gollent	DataReader dataReader((uint8*)fDebugLineSection->Data() + offset,
1765c4120026SRene Gollent		fDebugLineSection->Size() - offset, unit->AddressSize());
1766c4120026SRene Gollent
1767c4120026SRene Gollent	// unit length
1768c4120026SRene Gollent	bool dwarf64;
1769c4120026SRene Gollent	uint64 unitLength = dataReader.ReadInitialLength(dwarf64);
1770c4120026SRene Gollent	if (unitLength > (uint64)dataReader.BytesRemaining())
1771c4120026SRene Gollent		return B_BAD_DATA;
1772c4120026SRene Gollent	off_t unitOffset = dataReader.Offset();
1773c4120026SRene Gollent
1774c4120026SRene Gollent	// version (uhalf)
1775c4120026SRene Gollent	uint16 version = dataReader.Read<uint16>(0);
1776c4120026SRene Gollent
1777c4120026SRene Gollent	// header_length (4/8)
1778c4120026SRene Gollent	uint64 headerLength = dwarf64
1779c4120026SRene Gollent		? dataReader.Read<uint64>(0) : (uint64)dataReader.Read<uint32>(0);
1780c4120026SRene Gollent	off_t headerOffset = dataReader.Offset();
1781c4120026SRene Gollent
1782c4120026SRene Gollent	if ((uint64)dataReader.BytesRemaining() < headerLength)
1783c4120026SRene Gollent		return B_BAD_DATA;
1784c4120026SRene Gollent
1785c4120026SRene Gollent	// minimum instruction length
1786c4120026SRene Gollent	uint8 minInstructionLength = dataReader.Read<uint8>(0);
1787c4120026SRene Gollent
1788c4120026SRene Gollent	// default is statement
1789c4120026SRene Gollent	bool defaultIsStatement = dataReader.Read<uint8>(0) != 0;
1790c4120026SRene Gollent
1791c4120026SRene Gollent	// line_base (sbyte)
1792c4120026SRene Gollent	int8 lineBase = (int8)dataReader.Read<uint8>(0);
1793c4120026SRene Gollent
1794c4120026SRene Gollent	// line_range (ubyte)
1795c4120026SRene Gollent	uint8 lineRange = dataReader.Read<uint8>(0);
1796c4120026SRene Gollent
1797c4120026SRene Gollent	// opcode_base (ubyte)
1798c4120026SRene Gollent	uint8 opcodeBase = dataReader.Read<uint8>(0);
1799c4120026SRene Gollent
1800c4120026SRene Gollent	// standard_opcode_lengths (ubyte[])
1801c4120026SRene Gollent	const uint8* standardOpcodeLengths = (const uint8*)dataReader.Data();
1802c4120026SRene Gollent	dataReader.Skip(opcodeBase - 1);
1803c4120026SRene Gollent
1804c4120026SRene Gollent	if (dataReader.HasOverflow())
1805c4120026SRene Gollent		return B_BAD_DATA;
1806c4120026SRene Gollent
1807c4120026SRene Gollent	if (version != 2 && version != 3)
1808c4120026SRene Gollent		return B_UNSUPPORTED;
1809c4120026SRene Gollent
18107483c98dSIngo Weinhold	TRACE_LINES("  unitLength:           %" B_PRIu64 "\n", unitLength);
1811c4120026SRene Gollent	TRACE_LINES("  version:              %u\n", version);
18127483c98dSIngo Weinhold	TRACE_LINES("  headerLength:         %" B_PRIu64 "\n", headerLength);
1813c4120026SRene Gollent	TRACE_LINES("  minInstructionLength: %u\n", minInstructionLength);
1814c4120026SRene Gollent	TRACE_LINES("  defaultIsStatement:   %d\n", defaultIsStatement);
1815c4120026SRene Gollent	TRACE_LINES("  lineBase:             %d\n", lineBase);
1816c4120026SRene Gollent	TRACE_LINES("  lineRange:            %u\n", lineRange);
1817c4120026SRene Gollent	TRACE_LINES("  opcodeBase:           %u\n", opcodeBase);
1818c4120026SRene Gollent
1819c4120026SRene Gollent	// include directories
1820c4120026SRene Gollent	TRACE_LINES("  include directories:\n");
1821c4120026SRene Gollent	while (const char* directory = dataReader.ReadString()) {
1822c4120026SRene Gollent		if (*directory == '\0')
1823c4120026SRene Gollent			break;
1824c4120026SRene Gollent		TRACE_LINES("    \"%s\"\n", directory);
1825c4120026SRene Gollent
1826c4120026SRene Gollent		if (!unit->AddDirectory(directory))
1827c4120026SRene Gollent			return B_NO_MEMORY;
1828c4120026SRene Gollent	}
1829c4120026SRene Gollent
1830c4120026SRene Gollent	// file names
1831c4120026SRene Gollent	TRACE_LINES("  files:\n");
1832c4120026SRene Gollent	while (const char* file = dataReader.ReadString()) {
1833c4120026SRene Gollent		if (*file == '\0')
1834c4120026SRene Gollent			break;
1835c4120026SRene Gollent		uint64 dirIndex = dataReader.ReadUnsignedLEB128(0);
1836c4120026SRene Gollent		TRACE_LINES_ONLY(uint64 modificationTime =)
1837c4120026SRene Gollent			dataReader.ReadUnsignedLEB128(0);
1838c4120026SRene Gollent		TRACE_LINES_ONLY(uint64 fileLength =)
1839c4120026SRene Gollent			dataReader.ReadUnsignedLEB128(0);
1840c4120026SRene Gollent
1841c4120026SRene Gollent		if (dataReader.HasOverflow())
1842c4120026SRene Gollent			return B_BAD_DATA;
1843c4120026SRene Gollent
18447483c98dSIngo Weinhold		TRACE_LINES("    \"%s\", dir index: %" B_PRIu64 ", mtime: %" B_PRIu64
18457483c98dSIngo Weinhold			", length: %" B_PRIu64 "\n", file, dirIndex, modificationTime,
18467483c98dSIngo Weinhold			fileLength);
1847c4120026SRene Gollent
1848c4120026SRene Gollent		if (!unit->AddFile(file, dirIndex))
1849c4120026SRene Gollent			return B_NO_MEMORY;
1850c4120026SRene Gollent	}
1851c4120026SRene Gollent
1852c4120026SRene Gollent	off_t readerOffset = dataReader.Offset();
1853c4120026SRene Gollent	if ((uint64)readerOffset > readerOffset + headerLength)
1854c4120026SRene Gollent		return B_BAD_DATA;
1855c4120026SRene Gollent	off_t offsetToProgram = headerOffset + headerLength - readerOffset;
1856c4120026SRene Gollent
1857c4120026SRene Gollent	const uint8* program = (uint8*)dataReader.Data() + offsetToProgram;
1858c4120026SRene Gollent	size_t programSize = unitLength - (readerOffset - unitOffset);
1859c4120026SRene Gollent
1860c4120026SRene Gollent	return unit->GetLineNumberProgram().Init(program, programSize,
1861c4120026SRene Gollent		minInstructionLength, defaultIsStatement, lineBase, lineRange,
1862c4120026SRene Gollent			opcodeBase, standardOpcodeLengths);
1863c4120026SRene Gollent}
1864c4120026SRene Gollent
1865c4120026SRene Gollent
1866c4120026SRene Gollentstatus_t
1867d390ebeeSRene GollentDwarfFile::_UnwindCallFrame(CompilationUnit* unit, uint8 addressSize,
1868d390ebeeSRene Gollent	DIESubprogram* subprogramEntry, target_addr_t location,
1869d390ebeeSRene Gollent	const FDELookupInfo* info, const DwarfTargetInterface* inputInterface,
1870c4120026SRene Gollent	DwarfTargetInterface* outputInterface, target_addr_t& _framePointer)
1871c4120026SRene Gollent{
1872d390ebeeSRene Gollent	ElfSection* currentFrameSection = (info->ehFrame)
1873c4120026SRene Gollent		? fEHFrameSection : fDebugFrameSection;
1874c4120026SRene Gollent
18757483c98dSIngo Weinhold	TRACE_CFI("DwarfFile::_UnwindCallFrame(%#" B_PRIx64 ")\n", location);
1876c4120026SRene Gollent
1877c4120026SRene Gollent	DataReader dataReader((uint8*)currentFrameSection->Data(),
18785bda396eSRene Gollent		currentFrameSection->Size(), unit != NULL
18795bda396eSRene Gollent			? unit->AddressSize() : addressSize);
1880d390ebeeSRene Gollent	dataReader.SeekAbsolute(info->fdeOffset);
1881c4120026SRene Gollent
1882d390ebeeSRene Gollent	bool dwarf64;
1883d390ebeeSRene Gollent	uint64 length = dataReader.ReadInitialLength(dwarf64);
1884d390ebeeSRene Gollent	uint64 lengthOffset = dataReader.Offset();
1885d390ebeeSRene Gollent
1886d390ebeeSRene Gollent	CfaContext context;
1887d390ebeeSRene Gollent	CIEAugmentation cieAugmentation;
1888d390ebeeSRene Gollent	// when using .eh_frame format, we need to parse the CIE's
1889d390ebeeSRene Gollent	// augmentation up front in order to know how the FDE's addresses
1890d390ebeeSRene Gollent	//  will be represented
1891d390ebeeSRene Gollent	DataReader cieReader;
1892d390ebeeSRene Gollent	off_t cieRemaining;
1893d390ebeeSRene Gollent	status_t error = _ParseCIEHeader(currentFrameSection,
1894d390ebeeSRene Gollent		info->ehFrame, unit, addressSize, context, info->cieOffset,
1895d390ebeeSRene Gollent		cieAugmentation, cieReader, cieRemaining);
1896d390ebeeSRene Gollent	if (error != B_OK)
1897d390ebeeSRene Gollent		return error;
1898d390ebeeSRene Gollent	if (cieReader.HasOverflow())
1899d390ebeeSRene Gollent		return B_BAD_DATA;
1900d390ebeeSRene Gollent	if (cieRemaining < 0)
1901d390ebeeSRene Gollent		return B_BAD_DATA;
1902c4120026SRene Gollent
1903d390ebeeSRene Gollent	// skip CIE ID, initial offset and range, since we already know those
1904d390ebeeSRene Gollent	// from FDELookupInfo.
1905d390ebeeSRene Gollent	dwarf64	? dataReader.Read<uint64>(0) : dataReader.Read<uint32>(0);
1906d390ebeeSRene Gollent	cieAugmentation.ReadEncodedAddress(dataReader, fElfFile,
1907d390ebeeSRene Gollent		currentFrameSection);
1908d390ebeeSRene Gollent	cieAugmentation.ReadEncodedAddress(dataReader, fElfFile,
1909d390ebeeSRene Gollent		currentFrameSection, true);
1910d390ebeeSRene Gollent
1911d390ebeeSRene Gollent	TRACE_CFI("  found fde: length: %" B_PRIu64 " (%" B_PRIdOFF
1912d390ebeeSRene Gollent		"), CIE offset: %#" B_PRIx64 ", location: %#" B_PRIx64 ", "
1913d390ebeeSRene Gollent		"range: %#" B_PRIx64 "\n", length, dataReader.BytesRemaining(),
1914d390ebeeSRene Gollent		info->cieOffset, info->start, info->end - info->start);
1915d390ebeeSRene Gollent
1916d390ebeeSRene Gollent	context.SetLocation(location, info->start);
1917d390ebeeSRene Gollent	uint32 registerCount = outputInterface->CountRegisters();
1918d390ebeeSRene Gollent	error = context.Init(registerCount);
1919d390ebeeSRene Gollent	if (error != B_OK)
1920d390ebeeSRene Gollent		return error;
1921c4120026SRene Gollent
1922d390ebeeSRene Gollent	error = outputInterface->InitRegisterRules(context);
1923d390ebeeSRene Gollent	if (error != B_OK)
1924d390ebeeSRene Gollent		return error;
1925c4120026SRene Gollent
1926d390ebeeSRene Gollent	// process the CIE's frame info instructions
1927d390ebeeSRene Gollent	cieReader = cieReader.RestrictedReader(cieRemaining);
1928d390ebeeSRene Gollent	error = _ParseFrameInfoInstructions(unit, context,
1929d390ebeeSRene Gollent		cieReader, cieAugmentation);
1930d390ebeeSRene Gollent	if (error != B_OK)
1931d390ebeeSRene Gollent		return error;
193296a4619bSRene Gollent
1933d390ebeeSRene Gollent	// read the FDE augmentation data (if any)
1934d390ebeeSRene Gollent	FDEAugmentation fdeAugmentation;
1935d390ebeeSRene Gollent	error = cieAugmentation.ReadFDEData(dataReader,
1936d390ebeeSRene Gollent		fdeAugmentation);
1937d390ebeeSRene Gollent	if (error != B_OK) {
1938d390ebeeSRene Gollent		TRACE_CFI("  failed to read FDE augmentation data!\n");
1939d390ebeeSRene Gollent		return error;
1940d390ebeeSRene Gollent	}
194196a4619bSRene Gollent
1942d390ebeeSRene Gollent	error = context.SaveInitialRuleSet();
1943d390ebeeSRene Gollent	if (error != B_OK)
1944d390ebeeSRene Gollent		return error;
1945d390ebeeSRene Gollent
1946c87c9579SRene Gollent	uint64 remaining = lengthOffset + length - dataReader.Offset();
1947c87c9579SRene Gollent	if (remaining < 0)
1948c87c9579SRene Gollent		return B_BAD_DATA;
1949c87c9579SRene Gollent
1950d390ebeeSRene Gollent	DataReader restrictedReader =
1951d390ebeeSRene Gollent		dataReader.RestrictedReader(remaining);
1952d390ebeeSRene Gollent	error = _ParseFrameInfoInstructions(unit, context,
1953d390ebeeSRene Gollent		restrictedReader, cieAugmentation);
1954d390ebeeSRene Gollent	if (error != B_OK)
1955d390ebeeSRene Gollent		return error;
1956d390ebeeSRene Gollent
1957d390ebeeSRene Gollent	TRACE_CFI("  found row!\n");
1958d390ebeeSRene Gollent
1959d390ebeeSRene Gollent	// apply the rules of the final row
1960d390ebeeSRene Gollent	// get the frameAddress first
1961d390ebeeSRene Gollent	target_addr_t frameAddress;
1962d390ebeeSRene Gollent	CfaCfaRule* cfaCfaRule = context.GetCfaCfaRule();
1963d390ebeeSRene Gollent	switch (cfaCfaRule->Type()) {
1964d390ebeeSRene Gollent		case CFA_CFA_RULE_REGISTER_OFFSET:
1965d390ebeeSRene Gollent		{
1966d390ebeeSRene Gollent			BVariant value;
1967d390ebeeSRene Gollent			if (!inputInterface->GetRegisterValue(
1968d390ebeeSRene Gollent					cfaCfaRule->Register(), value)
1969d390ebeeSRene Gollent				|| !value.IsNumber()) {
1970d390ebeeSRene Gollent				return B_UNSUPPORTED;
1971d390ebeeSRene Gollent			}
1972d390ebeeSRene Gollent			frameAddress = value.ToUInt64() + cfaCfaRule->Offset();
1973d390ebeeSRene Gollent			break;
1974d390ebeeSRene Gollent		}
1975d390ebeeSRene Gollent		case CFA_CFA_RULE_EXPRESSION:
1976d390ebeeSRene Gollent		{
1977d390ebeeSRene Gollent			error = EvaluateExpression(unit, addressSize,
1978d390ebeeSRene Gollent				subprogramEntry,
1979d390ebeeSRene Gollent				cfaCfaRule->Expression().block,
1980d390ebeeSRene Gollent				cfaCfaRule->Expression().size,
1981d390ebeeSRene Gollent				inputInterface, location, 0, 0, false,
1982d390ebeeSRene Gollent				frameAddress);
198383a52221SRene Gollent			if (error != B_OK)
198483a52221SRene Gollent				return error;
1985d390ebeeSRene Gollent			break;
1986d390ebeeSRene Gollent		}
1987d390ebeeSRene Gollent		case CFA_CFA_RULE_UNDEFINED:
1988d390ebeeSRene Gollent		default:
1989d390ebeeSRene Gollent			return B_BAD_VALUE;
1990d390ebeeSRene Gollent	}
199196a4619bSRene Gollent
1992d390ebeeSRene Gollent	TRACE_CFI("  frame address: %#" B_PRIx64 "\n", frameAddress);
1993c4120026SRene Gollent
1994d390ebeeSRene Gollent	// apply the register rules
1995d390ebeeSRene Gollent	for (uint32 i = 0; i < registerCount; i++) {
1996d390ebeeSRene Gollent		TRACE_CFI("  reg %" B_PRIu32 "\n", i);
1997c4120026SRene Gollent
1998d390ebeeSRene Gollent		uint32 valueType = outputInterface->RegisterValueType(i);
1999d390ebeeSRene Gollent		if (valueType == 0)
2000d390ebeeSRene Gollent			continue;
200116b8573bSRene Gollent
2002d390ebeeSRene Gollent		CfaRule* rule = context.RegisterRule(i);
2003d390ebeeSRene Gollent		if (rule == NULL)
2004d390ebeeSRene Gollent			continue;
2005c4120026SRene Gollent
2006d390ebeeSRene Gollent		// apply the rule
2007d390ebeeSRene Gollent		switch (rule->Type()) {
2008d390ebeeSRene Gollent			case CFA_RULE_SAME_VALUE:
2009d390ebeeSRene Gollent			{
2010d390ebeeSRene Gollent				TRACE_CFI("  -> CFA_RULE_SAME_VALUE\n");
201191c6759fSIngo Weinhold
2012d390ebeeSRene Gollent				BVariant value;
2013d390ebeeSRene Gollent				if (inputInterface->GetRegisterValue(i, value))
2014d390ebeeSRene Gollent					outputInterface->SetRegisterValue(i, value);
2015d390ebeeSRene Gollent				break;
2016d390ebeeSRene Gollent			}
2017d390ebeeSRene Gollent			case CFA_RULE_LOCATION_OFFSET:
2018d390ebeeSRene Gollent			{
2019d390ebeeSRene Gollent				TRACE_CFI("  -> CFA_RULE_LOCATION_OFFSET: %"
2020d390ebeeSRene Gollent					B_PRId64 "\n", rule->Offset());
2021d390ebeeSRene Gollent
2022d390ebeeSRene Gollent				BVariant value;
2023d390ebeeSRene Gollent				if (inputInterface->ReadValueFromMemory(
2024d390ebeeSRene Gollent						frameAddress + rule->Offset(), valueType,
2025d390ebeeSRene Gollent						value)) {
2026d390ebeeSRene Gollent					outputInterface->SetRegisterValue(i, value);
2027c4120026SRene Gollent				}
2028d390ebeeSRene Gollent				break;
2029d390ebeeSRene Gollent			}
2030d390ebeeSRene Gollent			case CFA_RULE_VALUE_OFFSET:
2031d390ebeeSRene Gollent				TRACE_CFI("  -> CFA_RULE_VALUE_OFFSET\n");
203291c6759fSIngo Weinhold
2033d390ebeeSRene Gollent				outputInterface->SetRegisterValue(i,
2034d390ebeeSRene Gollent					frameAddress + rule->Offset());
2035d390ebeeSRene Gollent				break;
2036d390ebeeSRene Gollent			case CFA_RULE_REGISTER:
2037d390ebeeSRene Gollent			{
2038d390ebeeSRene Gollent				TRACE_CFI("  -> CFA_RULE_REGISTER\n");
2039d390ebeeSRene Gollent
2040d390ebeeSRene Gollent				BVariant value;
2041d390ebeeSRene Gollent				if (inputInterface->GetRegisterValue(
2042d390ebeeSRene Gollent						rule->Register(), value)) {
2043d390ebeeSRene Gollent					outputInterface->SetRegisterValue(i, value);
2044d390ebeeSRene Gollent				}
2045d390ebeeSRene Gollent				break;
2046d390ebeeSRene Gollent			}
2047d390ebeeSRene Gollent			case CFA_RULE_LOCATION_EXPRESSION:
2048d390ebeeSRene Gollent			{
2049d390ebeeSRene Gollent				TRACE_CFI("  -> CFA_RULE_LOCATION_EXPRESSION\n");
2050d390ebeeSRene Gollent
2051d390ebeeSRene Gollent				target_addr_t address;
2052d390ebeeSRene Gollent				error = EvaluateExpression(unit, addressSize,
2053d390ebeeSRene Gollent					subprogramEntry,
2054d390ebeeSRene Gollent					rule->Expression().block,
2055d390ebeeSRene Gollent					rule->Expression().size,
2056d390ebeeSRene Gollent					inputInterface, location, frameAddress,
2057d390ebeeSRene Gollent					frameAddress, true, address);
2058d390ebeeSRene Gollent				BVariant value;
2059d390ebeeSRene Gollent				if (error == B_OK
2060d390ebeeSRene Gollent					&& inputInterface->ReadValueFromMemory(address,
2061d390ebeeSRene Gollent						valueType, value)) {
2062d390ebeeSRene Gollent					outputInterface->SetRegisterValue(i, value);
2063d390ebeeSRene Gollent				}
2064d390ebeeSRene Gollent				break;
2065c4120026SRene Gollent			}
2066d390ebeeSRene Gollent			case CFA_RULE_VALUE_EXPRESSION:
2067d390ebeeSRene Gollent			{
2068d390ebeeSRene Gollent				TRACE_CFI("  -> CFA_RULE_VALUE_EXPRESSION\n");
2069d390ebeeSRene Gollent
2070d390ebeeSRene Gollent				target_addr_t value;
2071d390ebeeSRene Gollent				error = EvaluateExpression(unit, addressSize,
2072d390ebeeSRene Gollent					subprogramEntry,
2073d390ebeeSRene Gollent					rule->Expression().block,
2074d390ebeeSRene Gollent					rule->Expression().size,
2075d390ebeeSRene Gollent					inputInterface, location, frameAddress,
2076d390ebeeSRene Gollent					frameAddress, true, value);
2077d390ebeeSRene Gollent				if (error == B_OK)
2078d390ebeeSRene Gollent					outputInterface->SetRegisterValue(i, value);
2079d390ebeeSRene Gollent				break;
2080d390ebeeSRene Gollent			}
2081d390ebeeSRene Gollent			case CFA_RULE_UNDEFINED:
2082d390ebeeSRene Gollent				TRACE_CFI("  -> CFA_RULE_UNDEFINED\n");
2083d390ebeeSRene Gollent			default:
2084d390ebeeSRene Gollent				break;
2085c4120026SRene Gollent		}
208691c6759fSIngo Weinhold	}
208791c6759fSIngo Weinhold
2088d390ebeeSRene Gollent	_framePointer = frameAddress;
2089d390ebeeSRene Gollent
2090d390ebeeSRene Gollent	return B_OK;
209191c6759fSIngo Weinhold}
209291c6759fSIngo Weinhold
209391c6759fSIngo Weinhold
2094f7526300SIngo Weinholdstatus_t
209583a52221SRene GollentDwarfFile::_ParseCIEHeader(ElfSection* debugFrameSection,
209696a4619bSRene Gollent	bool usingEHFrameSection, CompilationUnit* unit, uint8 addressSize,
209796a4619bSRene Gollent	CfaContext& context, off_t cieOffset, CIEAugmentation& cieAugmentation,
209883a52221SRene Gollent	DataReader& dataReader, off_t& _cieRemaining)
2099f7526300SIngo Weinhold{
210005c7cd76SIngo Weinhold	if (cieOffset < 0 || (uint64)cieOffset >= debugFrameSection->Size())
2101f7526300SIngo Weinhold		return B_BAD_DATA;
2102f7526300SIngo Weinhold
210396a4619bSRene Gollent	dataReader.SetTo((uint8*)debugFrameSection->Data() + cieOffset,
21045bda396eSRene Gollent		debugFrameSection->Size() - cieOffset, unit != NULL
21055bda396eSRene Gollent			? unit->AddressSize() : addressSize);
2106f7526300SIngo Weinhold
2107f7526300SIngo Weinhold	// length
2108f7526300SIngo Weinhold	bool dwarf64;
2109e76262c8SStefano Ceccherini	uint64 length = dataReader.ReadInitialLength(dwarf64);
2110f7526300SIngo Weinhold	if (length > (uint64)dataReader.BytesRemaining())
2111f7526300SIngo Weinhold		return B_BAD_DATA;
21125bda396eSRene Gollent
211383a52221SRene Gollent	off_t lengthOffset = dataReader.Offset();
2114f7526300SIngo Weinhold
2115f7526300SIngo Weinhold	// CIE ID/CIE pointer
2116f7526300SIngo Weinhold