2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
6 #include "LineNumberProgram.h"
17 static const uint8 kLineNumberStandardOpcodeOperands
[]
18 = { 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 };
19 static const uint32 kLineNumberStandardOpcodeCount
= 12;
22 LineNumberProgram::LineNumberProgram(uint8 addressSize
)
26 fMinInstructionLength(0),
27 fDefaultIsStatement(0),
31 fAddressSize(addressSize
),
32 fStandardOpcodeLengths(NULL
)
37 LineNumberProgram::~LineNumberProgram()
43 LineNumberProgram::Init(const void* program
, size_t programSize
,
44 uint8 minInstructionLength
, bool defaultIsStatement
, int8 lineBase
,
45 uint8 lineRange
, uint8 opcodeBase
, const uint8
* standardOpcodeLengths
)
47 // first check the operand counts for the standard opcodes
48 uint8 standardOpcodeCount
= std::min((uint32
)opcodeBase
- 1,
49 kLineNumberStandardOpcodeCount
);
50 for (uint8 i
= 0; i
< standardOpcodeCount
; i
++) {
51 if (standardOpcodeLengths
[i
] != kLineNumberStandardOpcodeOperands
[i
]) {
52 WARNING("operand count for standard opcode %u does not what we "
59 fProgramSize
= programSize
;
60 fMinInstructionLength
= minInstructionLength
;
61 fDefaultIsStatement
= defaultIsStatement
;
63 fLineRange
= lineRange
;
64 fOpcodeBase
= opcodeBase
;
65 fStandardOpcodeLengths
= standardOpcodeLengths
;
72 LineNumberProgram::GetInitialState(State
& state
) const
78 state
.dataReader
.SetTo(fProgram
, fProgramSize
, fAddressSize
);
83 LineNumberProgram::GetNextRow(State
& state
) const
85 if (state
.isSequenceEnd
)
88 DataReader
& dataReader
= state
.dataReader
;
90 while (dataReader
.BytesRemaining() > 0) {
91 bool appendRow
= false;
92 uint8 opcode
= dataReader
.Read
<uint8
>(0);
93 if (opcode
>= fOpcodeBase
) {
95 uint adjustedOpcode
= opcode
- fOpcodeBase
;
96 state
.address
+= (adjustedOpcode
/ fLineRange
)
97 * fMinInstructionLength
;
98 state
.line
+= adjustedOpcode
% fLineRange
+ fLineBase
;
99 state
.isBasicBlock
= false;
100 state
.isPrologueEnd
= false;
101 state
.isEpilogueBegin
= false;
102 state
.discriminator
= 0;
104 } else if (opcode
> 0) {
108 state
.isBasicBlock
= false;
109 state
.isPrologueEnd
= false;
110 state
.isEpilogueBegin
= false;
112 state
.discriminator
= 0;
114 case DW_LNS_advance_pc
:
115 state
.address
+= dataReader
.ReadUnsignedLEB128(0)
116 * fMinInstructionLength
;
118 case DW_LNS_advance_line
:
119 state
.line
+= dataReader
.ReadSignedLEB128(0);
121 case DW_LNS_set_file
:
122 state
.file
= dataReader
.ReadUnsignedLEB128(0);
124 case DW_LNS_set_column
:
125 state
.column
= dataReader
.ReadUnsignedLEB128(0);
127 case DW_LNS_negate_stmt
:
128 state
.isStatement
= !state
.isStatement
;
130 case DW_LNS_set_basic_block
:
131 state
.isBasicBlock
= true;
133 case DW_LNS_const_add_pc
:
134 state
.address
+= ((255 - fOpcodeBase
) / fLineRange
)
135 * fMinInstructionLength
;
137 case DW_LNS_fixed_advance_pc
:
138 state
.address
+= dataReader
.Read
<uint16
>(0);
140 case DW_LNS_set_prologue_end
:
141 state
.isPrologueEnd
= true;
143 case DW_LNS_set_epilogue_begin
:
144 state
.isEpilogueBegin
= true;
147 state
.instructionSet
= dataReader
.ReadUnsignedLEB128(0);
150 WARNING("unsupported standard opcode %u\n", opcode
);
151 for (int32 i
= 0; i
< fStandardOpcodeLengths
[opcode
- 1];
153 dataReader
.ReadUnsignedLEB128(0);
158 uint32 instructionLength
= dataReader
.ReadUnsignedLEB128(0);
159 off_t instructionOffset
= dataReader
.Offset();
160 uint8 extendedOpcode
= dataReader
.Read
<uint8
>(0);
162 switch (extendedOpcode
) {
163 case DW_LNE_end_sequence
:
164 state
.isSequenceEnd
= true;
167 case DW_LNE_set_address
:
168 state
.address
= dataReader
.ReadAddress(0);
170 case DW_LNE_define_file
:
172 state
.explicitFile
= dataReader
.ReadString();
173 state
.explicitFileDirIndex
174 = dataReader
.ReadUnsignedLEB128(0);
175 dataReader
.ReadUnsignedLEB128(0); // modification time
176 dataReader
.ReadUnsignedLEB128(0); // file length
180 case DW_LNE_set_discriminator
:
182 state
.discriminator
= dataReader
.ReadUnsignedLEB128(0);
186 WARNING("unsupported extended opcode: %u\n",
191 dataReader
.Skip(instructionLength
192 - (dataReader
.Offset() - instructionOffset
));
195 if (dataReader
.HasOverflow())
207 LineNumberProgram::_SetToInitial(State
& state
) const
213 state
.isStatement
= fDefaultIsStatement
;
214 state
.isBasicBlock
= false;
215 state
.isSequenceEnd
= false;
216 state
.isPrologueEnd
= false;
217 state
.isEpilogueBegin
= false;
218 state
.instructionSet
= 0;
219 state
.discriminator
= 0;