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 }