File indexing completed on 2024-05-12 05:43:27
0001 /* 0002 Copyright (C) 2015 Volker Krause <vkrause@kde.org> 0003 0004 This program is free software; you can redistribute it and/or modify it 0005 under the terms of the GNU Library General Public License as published by 0006 the Free Software Foundation; either version 2 of the License, or (at your 0007 option) any later version. 0008 0009 This program is distributed in the hope that it will be useful, but WITHOUT 0010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0011 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 0012 License for more details. 0013 0014 You should have received a copy of the GNU General Public License 0015 along with this program. If not, see <https://www.gnu.org/licenses/>. 0016 */ 0017 0018 #include "dwarfexpression.h" 0019 #include "dwarfleb128.h" 0020 0021 #include <QDebug> 0022 #include <QString> 0023 #include <QtEndian> 0024 0025 #include <dwarf.h> 0026 0027 #include <cassert> 0028 0029 enum class OperandType : int8_t { 0030 NONE, 0031 U1, 0032 S1, 0033 U2, 0034 S2, 0035 U4, 0036 S4, 0037 U8, 0038 S8, 0039 ADDR, 0040 ULEB128, 0041 SLEB128, 0042 ULEB128ULEB128, 0043 ULEB128SLEB128, 0044 ULEB128BLOCK 0045 }; 0046 0047 struct opcode_t { 0048 uint8_t opCode; 0049 OperandType opType; 0050 const char* name; 0051 }; 0052 0053 #define OP(code, opType) { DW_OP_ ## code, OperandType:: opType, "DW_OP_" #code } 0054 0055 static const opcode_t opcodes[] { 0056 OP(addr, ADDR), 0057 OP(deref, NONE), 0058 OP(const1u, U1), 0059 OP(const1s, S1), 0060 OP(const2u, U2), 0061 OP(const2s, S2), 0062 OP(const4u, U4), 0063 OP(const4s, S4), 0064 OP(const8u, U8), 0065 OP(const8s, S8), 0066 OP(constu, ULEB128), 0067 OP(consts, SLEB128), 0068 OP(dup, NONE), 0069 OP(drop, NONE), 0070 OP(over, NONE), 0071 OP(pick, U1), 0072 OP(swap, NONE), 0073 OP(rot, NONE), 0074 OP(xderef, NONE), 0075 OP(abs, NONE), 0076 OP(and, NONE), 0077 OP(div, NONE), 0078 OP(minus, NONE), 0079 OP(mod, NONE), 0080 OP(mul, NONE), 0081 OP(neg, NONE), 0082 OP(not, NONE), 0083 OP(or, NONE), 0084 OP(plus, NONE), 0085 OP(plus_uconst, ULEB128), 0086 OP(shl, NONE), 0087 OP(shr, NONE), 0088 OP(shra, NONE), 0089 OP(xor, NONE), 0090 OP(bra, S2), 0091 OP(eq, NONE), 0092 OP(ge, NONE), 0093 OP(gt, NONE), 0094 OP(le, NONE), 0095 OP(lt, NONE), 0096 OP(ne, NONE), 0097 OP(skip, S2), 0098 OP(lit0, NONE), 0099 OP(lit1, NONE), 0100 OP(lit2, NONE), 0101 OP(lit3, NONE), 0102 OP(lit4, NONE), 0103 OP(lit5, NONE), 0104 OP(lit6, NONE), 0105 OP(lit7, NONE), 0106 OP(lit8, NONE), 0107 OP(lit9, NONE), 0108 OP(lit10, NONE), 0109 OP(lit11, NONE), 0110 OP(lit12, NONE), 0111 OP(lit13, NONE), 0112 OP(lit14, NONE), 0113 OP(lit15, NONE), 0114 OP(lit16, NONE), 0115 OP(lit17, NONE), 0116 OP(lit18, NONE), 0117 OP(lit19, NONE), 0118 OP(lit20, NONE), 0119 OP(lit21, NONE), 0120 OP(lit22, NONE), 0121 OP(lit23, NONE), 0122 OP(lit24, NONE), 0123 OP(lit25, NONE), 0124 OP(lit26, NONE), 0125 OP(lit27, NONE), 0126 OP(lit28, NONE), 0127 OP(lit29, NONE), 0128 OP(lit30, NONE), 0129 OP(lit31, NONE), 0130 OP(reg0, NONE), 0131 OP(reg1, NONE), 0132 OP(reg2, NONE), 0133 OP(reg3, NONE), 0134 OP(reg4, NONE), 0135 OP(reg5, NONE), 0136 OP(reg6, NONE), 0137 OP(reg7, NONE), 0138 OP(reg8, NONE), 0139 OP(reg9, NONE), 0140 OP(reg10, NONE), 0141 OP(reg11, NONE), 0142 OP(reg12, NONE), 0143 OP(reg13, NONE), 0144 OP(reg14, NONE), 0145 OP(reg15, NONE), 0146 OP(reg16, NONE), 0147 OP(reg17, NONE), 0148 OP(reg18, NONE), 0149 OP(reg19, NONE), 0150 OP(reg20, NONE), 0151 OP(reg21, NONE), 0152 OP(reg22, NONE), 0153 OP(reg23, NONE), 0154 OP(reg24, NONE), 0155 OP(reg25, NONE), 0156 OP(reg26, NONE), 0157 OP(reg27, NONE), 0158 OP(reg28, NONE), 0159 OP(reg29, NONE), 0160 OP(reg30, NONE), 0161 OP(reg31, NONE), 0162 OP(breg0, SLEB128), 0163 OP(breg1, SLEB128), 0164 OP(breg2, SLEB128), 0165 OP(breg3, SLEB128), 0166 OP(breg4, SLEB128), 0167 OP(breg5, SLEB128), 0168 OP(breg6, SLEB128), 0169 OP(breg7, SLEB128), 0170 OP(breg8, SLEB128), 0171 OP(breg9, SLEB128), 0172 OP(breg10, SLEB128), 0173 OP(breg11, SLEB128), 0174 OP(breg12, SLEB128), 0175 OP(breg13, SLEB128), 0176 OP(breg14, SLEB128), 0177 OP(breg15, SLEB128), 0178 OP(breg16, SLEB128), 0179 OP(breg17, SLEB128), 0180 OP(breg18, SLEB128), 0181 OP(breg19, SLEB128), 0182 OP(breg20, SLEB128), 0183 OP(breg21, SLEB128), 0184 OP(breg22, SLEB128), 0185 OP(breg23, SLEB128), 0186 OP(breg24, SLEB128), 0187 OP(breg25, SLEB128), 0188 OP(breg26, SLEB128), 0189 OP(breg27, SLEB128), 0190 OP(breg28, SLEB128), 0191 OP(breg29, SLEB128), 0192 OP(breg30, SLEB128), 0193 OP(breg31, SLEB128), 0194 OP(regx, ULEB128), 0195 OP(fbreg, SLEB128), 0196 OP(bregx, ULEB128SLEB128), 0197 OP(piece, ULEB128), 0198 OP(deref_size, U1), 0199 OP(xderef_size, U1), 0200 OP(nop, NONE), 0201 OP(push_object_address, NONE), 0202 OP(call2, U2), 0203 OP(call4, U4), 0204 OP(call_ref, ADDR), 0205 OP(form_tls_address, NONE), 0206 OP(call_frame_cfa, NONE), 0207 OP(bit_piece, ULEB128ULEB128), 0208 OP(implicit_value, ULEB128BLOCK), 0209 OP(stack_value, NONE), 0210 OP(GNU_push_tls_address, NONE), 0211 OP(GNU_uninit, NONE), 0212 OP(GNU_encoded_addr, NONE), 0213 OP(GNU_implicit_pointer, NONE), 0214 OP(GNU_entry_value, NONE) 0215 }; 0216 0217 #undef OP 0218 0219 static const int opcodesSize = sizeof(opcodes) / sizeof(opcode_t); 0220 0221 static const opcode_t* opcode(uint8_t code) 0222 { 0223 // TODO use the fact that opcodes is sorted... 0224 for (int i = 0; i < opcodesSize; ++i) { 0225 if (opcodes[i].opCode == code) 0226 return &opcodes[i]; 0227 } 0228 return nullptr; 0229 } 0230 0231 DwarfExpression::DwarfExpression() : m_addrSize(0) 0232 { 0233 } 0234 0235 DwarfExpression::DwarfExpression(Dwarf_Ptr block, Dwarf_Unsigned len, uint8_t addrSize) : 0236 m_addrSize(addrSize) 0237 { 0238 assert(m_addrSize == 4 || m_addrSize == 8); 0239 m_block = QByteArray::fromRawData(static_cast<const char*>(block), len); 0240 } 0241 0242 QString DwarfExpression::displayString() const 0243 { 0244 if (m_block.isEmpty()) 0245 return QStringLiteral("<empty>"); 0246 0247 QString s; 0248 for (int i = 0; i < m_block.size(); ++i) { 0249 const auto op = opcode(m_block.at(i)); 0250 if (!op) { 0251 s += QLatin1String("unknown<0x") + QString::number((uint8_t)m_block.at(i), 16) + QLatin1Char('>'); 0252 } else { 0253 s += op->name; 0254 int size = 0; 0255 0256 // TODO correct endianess conversion 0257 #define NUM2STR(type) \ 0258 {\ 0259 size = sizeof(type); \ 0260 assert(m_block.size() > i + size); \ 0261 const auto value = readNumber<type>(i + 1); \ 0262 s += ' ' + QString::number(value); \ 0263 break; \ 0264 } 0265 0266 switch (op->opType) { 0267 case OperandType::NONE: 0268 break; 0269 0270 case OperandType::U1: 0271 NUM2STR(uint8_t) 0272 case OperandType::U2: 0273 NUM2STR(uint16_t) 0274 case OperandType::U4: 0275 NUM2STR(uint32_t) 0276 case OperandType::U8: 0277 NUM2STR(quint64) // uint64_t != quint64... 0278 0279 case OperandType::S1: 0280 NUM2STR(int8_t) 0281 case OperandType::S2: 0282 NUM2STR(int16_t) 0283 case OperandType::S4: 0284 NUM2STR(int32_t) 0285 case OperandType::S8: 0286 NUM2STR(quint64) 0287 0288 case OperandType::ADDR: 0289 { 0290 uint64_t addr = 0; 0291 // TODO: endianess conversion 0292 memcpy(&addr, m_block.constData() + i + 1, m_addrSize); 0293 s += " 0x" + QByteArray::number(qulonglong(addr), 16); 0294 size = m_addrSize; 0295 break; 0296 } 0297 0298 case OperandType::ULEB128: 0299 s += ' ' + QString::number(DwarfLEB128::decodeUnsigned(m_block.constData() + i + 1, &size)); 0300 break; 0301 case OperandType::SLEB128: 0302 s += ' ' + QString::number(DwarfLEB128::decodeSigned(m_block.constData() + i + 1, &size)); 0303 break; 0304 case OperandType::ULEB128ULEB128: 0305 { 0306 // TODO 0307 assert(!"not implemented yet"); 0308 break; 0309 } 0310 case OperandType::ULEB128SLEB128: 0311 // TODO 0312 assert(!"not implemented yet"); 0313 break; 0314 case OperandType::ULEB128BLOCK: 0315 // TODO 0316 assert(!"not implemented yet"); 0317 break; 0318 } 0319 0320 #undef NUM2STR 0321 i += size; 0322 } 0323 if (i < m_block.size() - 1) 0324 s += ' '; 0325 } 0326 0327 return s; 0328 } 0329 0330 void DwarfExpression::push(uint64_t value) 0331 { 0332 m_stack.push(value); 0333 } 0334 0335 uint64_t DwarfExpression::top() const 0336 { 0337 return m_stack.top(); 0338 } 0339 0340 uint64_t DwarfExpression::pop() 0341 { 0342 return m_stack.pop(); 0343 } 0344 0345 bool DwarfExpression::evaluateSimple() 0346 { 0347 for (int i = 0; i < m_block.size();++i) { 0348 const auto consumed = evaluateOne(i); 0349 if (consumed < 0) 0350 return false; 0351 i += consumed; 0352 } 0353 return !m_stack.isEmpty(); 0354 } 0355 0356 template <typename T> T DwarfExpression::readNumber(int index) const 0357 { 0358 return qFromLittleEndian<T>(reinterpret_cast<const unsigned char*>(m_block.constData() + index)); 0359 } 0360 0361 int DwarfExpression::evaluateOne(int i) 0362 { 0363 const uint8_t code = m_block.at(i); 0364 switch (code) { 0365 case DW_OP_addr: 0366 if (m_addrSize == 4) 0367 push(readNumber<uint32_t>(i + 1)); 0368 else 0369 push(readNumber<quint64>(i + 1)); 0370 return m_addrSize; 0371 case DW_OP_const1u: 0372 push(readNumber<uint8_t>(i + 1)); 0373 return 1; 0374 case DW_OP_const1s: 0375 push(readNumber<int8_t>(i + 1)); 0376 return 1; 0377 case DW_OP_const2u: 0378 push(readNumber<uint16_t>(i + 1)); 0379 return 2; 0380 case DW_OP_const2s: 0381 push(readNumber<int16_t>(i + 1)); 0382 return 2; 0383 case DW_OP_const4u: 0384 push(readNumber<uint32_t>(i + 1)); 0385 return 4; 0386 case DW_OP_const4s: 0387 push(readNumber<int32_t>(i + 1)); 0388 return 4; 0389 case DW_OP_const8u: 0390 case DW_OP_const8s: // signed vs. unsigned doesn't matter here, we copy everything anyway 0391 push(readNumber<quint64>(i + 1)); 0392 return 8; 0393 case DW_OP_constu: 0394 { 0395 int size = 0; 0396 push(DwarfLEB128::decodeUnsigned(m_block.constData() + i + 1, &size)); 0397 return size; 0398 } 0399 case DW_OP_consts: 0400 { 0401 int size = 0; 0402 push(DwarfLEB128::decodeSigned(m_block.constData() + i + 1, &size)); 0403 return size; 0404 } 0405 0406 case DW_OP_dup: 0407 push(top()); 0408 return 0; 0409 0410 case DW_OP_minus: 0411 { 0412 const auto o1 = pop(); 0413 const auto o2 = pop(); 0414 push(o2 - o1); 0415 return 0; 0416 } 0417 case DW_OP_plus: 0418 push(pop() + pop()); 0419 return 0; 0420 } 0421 0422 if (code >= DW_OP_lit0 && code <= DW_OP_lit31) { 0423 push(code - DW_OP_lit0); 0424 return 0; 0425 } 0426 0427 const auto op = opcode(code); 0428 if (!op) { 0429 qWarning() << "unknown opcode: " << code; 0430 } else { 0431 qWarning() << "opcode" << op->name << "not yet implemented"; 0432 } 0433 0434 return -1; 0435 }