diff --git a/build.bat b/build.bat index abe5f279..1f6dfe34 100644 --- a/build.bat +++ b/build.bat @@ -145,6 +145,7 @@ if "%mule_main%"=="1" set didbuild=1 && del vc*.pdb mule*.pdb & if "%mule_module%"=="1" set didbuild=1 && %compile% ..\src\mule\mule_module.cpp %compile_link% %link_dll% %out%mule_module.dll || exit /b 1 if "%mule_hotload%"=="1" set didbuild=1 && %compile% ..\src\mule\mule_hotload_main.c %compile_link% %out%mule_hotload.exe & %compile% ..\src\mule\mule_hotload_module_main.c %compile_link% %link_dll% %out%mule_hotload_module.dll || exit /b 1 if "%torture%"=="1" set didbuild=1 && %compile% ..\src\torture\torture.c %compile_link% %out%torture.exe || exit /b1 +if "%dwarf_expr_test%"=="1" set didbuild=1 && %compile% ..\src\torture\dwarf_expr_test.c %compile_link% %out%dwarf_expr_test.exe || exit /b1 if "%mule_peb_trample%"=="1" ( set didbuild=1 if exist mule_peb_trample.exe move mule_peb_trample.exe mule_peb_trample_old_%random%.exe diff --git a/src/dwarf/dwarf.c b/src/dwarf/dwarf.c index 5a380b47..2d9a66e9 100644 --- a/src/dwarf/dwarf.c +++ b/src/dwarf/dwarf.c @@ -400,11 +400,11 @@ internal U64 dw_operand_count_from_expr_op(DW_ExprOp op) { switch (op) { -#define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT) case _ID: return _OPER_COUNT; - DW_Expr_V3_XList(X) - DW_Expr_V4_XList(X) - DW_Expr_V5_XList(X) - DW_Expr_GNU_XList(X) +#define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT, ...) case _ID: return _OPER_COUNT; + DW_Expr_V3_XList + DW_Expr_V4_XList + DW_Expr_V5_XList + DW_Expr_GNU_XList #undef X default: { NotImplemented; } break; } @@ -415,11 +415,11 @@ internal U64 dw_pop_count_from_expr_op(DW_ExprOp op) { switch (op) { -#define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT) case _ID: return _POP_COUNT; - DW_Expr_V3_XList(X) - DW_Expr_V4_XList(X) - DW_Expr_V5_XList(X) - DW_Expr_GNU_XList(X) +#define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT, ...) case _ID: return _POP_COUNT; + DW_Expr_V3_XList + DW_Expr_V4_XList + DW_Expr_V5_XList + DW_Expr_GNU_XList #undef X default: { NotImplemented; } break; } @@ -430,11 +430,25 @@ internal U64 dw_push_count_from_expr_op(DW_ExprOp op) { switch (op) { -#define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT) case _ID: return _PUSH_COUNT; - DW_Expr_V3_XList(X) - DW_Expr_V4_XList(X) - DW_Expr_V5_XList(X) - DW_Expr_GNU_XList(X) +#define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT, ...) case _ID: return _PUSH_COUNT; + DW_Expr_V3_XList + DW_Expr_V4_XList + DW_Expr_V5_XList + DW_Expr_GNU_XList +#undef X + default: { NotImplemented; } break; + } + return 0; +} + +internal DW_ExprOperandType * +dw_operand_types_from_expr_opcode(DW_ExprOp op) +{ +#define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT, _OPER_TYPE0, _OPER_TYPE1) case _ID: { local_persist DW_ExprOperandType t[] = { DW_ExprOperandType_##_OPER_TYPE0, DW_ExprOperandType_##_OPER_TYPE1 }; return t; } + switch (op) { + DW_Expr_V3_XList + DW_Expr_V4_XList + DW_Expr_V5_XList #undef X default: { NotImplemented; } break; } @@ -528,26 +542,26 @@ dw_string_from_expr_op(Arena *arena, DW_Version ver, DW_Ext ext, DW_ExprOp op) #define X(_N,...) case DW_ExprOp_##_N: result = str8_lit(Stringify(_N)); goto exit; if (ext & DW_Ext_GNU) { switch (op) { - DW_Expr_GNU_XList(X); + DW_Expr_GNU_XList; } } switch (ver) { case DW_Version_5: { switch (op) { - DW_Expr_V5_XList(X) + DW_Expr_V5_XList } } // fall-through case DW_Version_4: { switch (op) { - DW_Expr_V4_XList(X) + DW_Expr_V4_XList } } // fall-through case DW_Version_3: case DW_Version_2: case DW_Version_1: { switch (op) { - DW_Expr_V3_XList(X) + DW_Expr_V3_XList } } // fall-through case DW_Version_Null: diff --git a/src/dwarf/dwarf.h b/src/dwarf/dwarf.h index 44c7fc08..94dd6ade 100644 --- a/src/dwarf/dwarf.h +++ b/src/dwarf/dwarf.h @@ -1392,199 +1392,217 @@ typedef enum DW_CFA_Enum //////////////////////////////// // Expression Opcodes -// (opcode name, opcode id, operand count, pop count, push count) -#define DW_Expr_V3_XList(X) \ -X(Null, 0x00, 0, 0, 0) \ -X(Addr, 0x03, 1, 0, 1) \ -X(Deref, 0x06, 0, 1, 1) \ -X(Const1U, 0x08, 1, 0, 1) \ -X(Const1S, 0x09, 1, 0, 1) \ -X(Const2U, 0x0a, 1, 0, 1) \ -X(Const2S, 0x0b, 1, 0, 1) \ -X(Const4U, 0x0c, 1, 0, 1) \ -X(Const4S, 0x0d, 1, 0, 1) \ -X(Const8U, 0x0e, 1, 0, 1) \ -X(Const8S, 0x0f, 1, 0, 1) \ -X(ConstU, 0x10, 1, 0, 1) \ -X(ConstS, 0x11, 1, 0, 1) \ -X(Dup, 0x12, 0, 0, 1) \ -X(Drop, 0x13, 0, 1, 0) \ -X(Over, 0x14, 0, 0, 1) \ -X(Pick, 0x15, 1, 0, 1) \ -X(Swap, 0x16, 0, 0, 0) \ -X(Rot, 0x17, 0, 0, 0) \ -X(XDeref, 0x18, 0, 2, 1) \ -X(Abs, 0x19, 0, 1, 1) \ -X(And, 0x1a, 0, 2, 1) \ -X(Div, 0x1b, 0, 2, 1) \ -X(Minus, 0x1c, 0, 2, 1) \ -X(Mod, 0x1d, 0, 2, 1) \ -X(Mul, 0x1e, 0, 2, 1) \ -X(Neg, 0x1f, 0, 1, 1) \ -X(Not, 0x20, 0, 1, 1) \ -X(Or, 0x21, 0, 2, 1) \ -X(Plus, 0x22, 0, 2, 1) \ -X(PlusUConst, 0x23, 1, 1, 1) \ -X(Shl, 0x24, 0, 2, 1) \ -X(Shr, 0x25, 0, 2, 1) \ -X(Shra, 0x26, 0, 2, 1) \ -X(Xor, 0x27, 0, 2, 1) \ -X(Bra, 0x28, 1, 1, 0) \ -X(Eq, 0x29, 0, 2, 1) \ -X(Ge, 0x2a, 0, 2, 1) \ -X(Gt, 0x2b, 0, 2, 1) \ -X(Le, 0x2c, 0, 2, 1) \ -X(Lt, 0x2d, 0, 2, 1) \ -X(Ne, 0x2e, 0, 2, 1) \ -X(Skip, 0x2f, 1, 0, 0) \ -X(Lit0, 0x30, 0, 0, 0) \ -X(Lit1, 0x31, 0, 0, 0) \ -X(Lit2, 0x32, 0, 0, 0) \ -X(Lit3, 0x33, 0, 0, 0) \ -X(Lit4, 0x34, 0, 0, 0) \ -X(Lit5, 0x35, 0, 0, 0) \ -X(Lit6, 0x36, 0, 0, 0) \ -X(Lit7, 0x37, 0, 0, 0) \ -X(Lit8, 0x38, 0, 0, 0) \ -X(Lit9, 0x39, 0, 0, 0) \ -X(Lit10, 0x3a, 0, 0, 0) \ -X(Lit11, 0x3b, 0, 0, 0) \ -X(Lit12, 0x3c, 0, 0, 0) \ -X(Lit13, 0x3d, 0, 0, 0) \ -X(Lit14, 0x3e, 0, 0, 0) \ -X(Lit15, 0x3f, 0, 0, 0) \ -X(Lit16, 0x40, 0, 0, 0) \ -X(Lit17, 0x41, 0, 0, 0) \ -X(Lit18, 0x42, 0, 0, 0) \ -X(Lit19, 0x43, 0, 0, 0) \ -X(Lit20, 0x44, 0, 0, 0) \ -X(Lit21, 0x45, 0, 0, 0) \ -X(Lit22, 0x46, 0, 0, 0) \ -X(Lit23, 0x47, 0, 0, 0) \ -X(Lit24, 0x48, 0, 0, 0) \ -X(Lit25, 0x49, 0, 0, 0) \ -X(Lit26, 0x4a, 0, 0, 0) \ -X(Lit27, 0x4b, 0, 0, 0) \ -X(Lit28, 0x4c, 0, 0, 0) \ -X(Lit29, 0x4d, 0, 0, 0) \ -X(Lit30, 0x4e, 0, 0, 0) \ -X(Lit31, 0x4f, 0, 0, 0) \ -X(Reg0, 0x50, 0, 0, 1) \ -X(Reg1, 0x51, 0, 0, 1) \ -X(Reg2, 0x52, 0, 0, 1) \ -X(Reg3, 0x53, 0, 0, 1) \ -X(Reg4, 0x54, 0, 0, 1) \ -X(Reg5, 0x55, 0, 0, 1) \ -X(Reg6, 0x56, 0, 0, 1) \ -X(Reg7, 0x57, 0, 0, 1) \ -X(Reg8, 0x58, 0, 0, 1) \ -X(Reg9, 0x59, 0, 0, 1) \ -X(Reg10, 0x5a, 0, 0, 1) \ -X(Reg11, 0x5b, 0, 0, 1) \ -X(Reg12, 0x5c, 0, 0, 1) \ -X(Reg13, 0x5d, 0, 0, 1) \ -X(Reg14, 0x5e, 0, 0, 1) \ -X(Reg15, 0x5f, 0, 0, 1) \ -X(Reg16, 0x60, 0, 0, 1) \ -X(Reg17, 0x61, 0, 0, 1) \ -X(Reg18, 0x62, 0, 0, 1) \ -X(Reg19, 0x63, 0, 0, 1) \ -X(Reg20, 0x64, 0, 0, 1) \ -X(Reg21, 0x65, 0, 0, 1) \ -X(Reg22, 0x66, 0, 0, 1) \ -X(Reg23, 0x67, 0, 0, 1) \ -X(Reg24, 0x68, 0, 0, 1) \ -X(Reg25, 0x69, 0, 0, 1) \ -X(Reg26, 0x6a, 0, 0, 1) \ -X(Reg27, 0x6b, 0, 0, 1) \ -X(Reg28, 0x6c, 0, 0, 1) \ -X(Reg29, 0x6d, 0, 0, 1) \ -X(Reg30, 0x6e, 0, 0, 1) \ -X(Reg31, 0x6f, 0, 0, 1) \ -X(BReg0, 0x70, 1, 0, 1) \ -X(BReg1, 0x71, 1, 0, 1) \ -X(BReg2, 0x72, 1, 0, 1) \ -X(BReg3, 0x73, 1, 0, 1) \ -X(BReg4, 0x74, 1, 0, 1) \ -X(BReg5, 0x75, 1, 0, 1) \ -X(BReg6, 0x76, 1, 0, 1) \ -X(BReg7, 0x77, 1, 0, 1) \ -X(BReg8, 0x78, 1, 0, 1) \ -X(BReg9, 0x79, 1, 0, 1) \ -X(BReg10, 0x7a, 1, 0, 1) \ -X(BReg11, 0x7b, 1, 0, 1) \ -X(BReg12, 0x7c, 1, 0, 1) \ -X(BReg13, 0x7d, 1, 0, 1) \ -X(BReg14, 0x7e, 1, 0, 1) \ -X(BReg15, 0x7f, 1, 0, 1) \ -X(BReg16, 0x80, 1, 0, 1) \ -X(BReg17, 0x81, 1, 0, 1) \ -X(BReg18, 0x82, 1, 0, 1) \ -X(BReg19, 0x83, 1, 0, 1) \ -X(BReg20, 0x84, 1, 0, 1) \ -X(BReg21, 0x85, 1, 0, 1) \ -X(BReg22, 0x86, 1, 0, 1) \ -X(BReg23, 0x87, 1, 0, 1) \ -X(BReg24, 0x88, 1, 0, 1) \ -X(BReg25, 0x89, 1, 0, 1) \ -X(BReg26, 0x8a, 1, 0, 1) \ -X(BReg27, 0x8b, 1, 0, 1) \ -X(BReg28, 0x8c, 1, 0, 1) \ -X(BReg29, 0x8d, 1, 0, 1) \ -X(BReg30, 0x8e, 1, 0, 1) \ -X(BReg31, 0x8f, 1, 0, 1) \ -X(RegX, 0x90, 1, 0, 1) \ -X(FBReg, 0x91, 1, 0, 1) \ -X(BRegX, 0x92, 2, 0, 1) \ -X(Piece, 0x93, 1, 0, 0) \ -X(DerefSize, 0x94, 1, 1, 1) \ -X(XDerefSize, 0x95, 1, 2, 1) \ -X(Nop, 0x96, 0, 0, 0) \ -X(PushObjectAddress, 0x97, 0, 0, 1) \ -X(Call2, 0x98, 1, 0, 0) \ -X(Call4, 0x99, 1, 0, 0) \ -X(CallRef, 0x9a, 1, 0, 0) \ -X(FormTlsAddress, 0x9b, 0, 0, 1) \ -X(CallFrameCfa, 0x9c, 0, 0, 1) \ -X(BitPiece, 0x9d, 2, 0, 0) +typedef enum +{ + DW_ExprOperandType_Null, + DW_ExprOperandType_U8, + DW_ExprOperandType_U16, + DW_ExprOperandType_U32, + DW_ExprOperandType_U64, + DW_ExprOperandType_S8, + DW_ExprOperandType_S16, + DW_ExprOperandType_S32, + DW_ExprOperandType_S64, + DW_ExprOperandType_ULEB128, + DW_ExprOperandType_SLEB128, + DW_ExprOperandType_Addr, + DW_ExprOperandType_Block, + DW_ExprOperandType_DwarfUInt, +} DW_ExprOperandType; -#define DW_Expr_V4_XList(X) \ -X(ImplicitValue, 0x9e, 2, 0, 1) \ -X(StackValue, 0x9f, 0, 0, 0) +// (opcode name, opcode id, operand count, pop count, push count, operand0 type, operand1 type) +#define DW_Expr_V3_XList \ + X(Null, 0x00, 0, 0, 0, Null, Null) \ + X(Addr, 0x03, 1, 0, 1, Addr, Null) \ + X(Deref, 0x06, 0, 1, 1, Null, Null) \ + X(Const1U, 0x08, 1, 0, 1, U8, Null) \ + X(Const1S, 0x09, 1, 0, 1, S8, Null) \ + X(Const2U, 0x0a, 1, 0, 1, U16, Null) \ + X(Const2S, 0x0b, 1, 0, 1, S16, Null) \ + X(Const4U, 0x0c, 1, 0, 1, U32, Null) \ + X(Const4S, 0x0d, 1, 0, 1, S32, Null) \ + X(Const8U, 0x0e, 1, 0, 1, U64, Null) \ + X(Const8S, 0x0f, 1, 0, 1, S64, Null) \ + X(ConstU, 0x10, 1, 0, 1, ULEB128, Null) \ + X(ConstS, 0x11, 1, 0, 1, SLEB128, Null) \ + X(Dup, 0x12, 0, 0, 1, Null, Null) \ + X(Drop, 0x13, 0, 1, 0, Null, Null) \ + X(Over, 0x14, 0, 0, 1, Null, Null) \ + X(Pick, 0x15, 1, 0, 1, U8, Null) \ + X(Swap, 0x16, 0, 0, 0, Null, Null) \ + X(Rot, 0x17, 0, 0, 0, Null, Null) \ + X(XDeref, 0x18, 0, 2, 1, Null, Null) \ + X(Abs, 0x19, 0, 1, 1, Null, Null) \ + X(And, 0x1a, 0, 2, 1, Null, Null) \ + X(Div, 0x1b, 0, 2, 1, Null, Null) \ + X(Minus, 0x1c, 0, 2, 1, Null, Null) \ + X(Mod, 0x1d, 0, 2, 1, Null, Null) \ + X(Mul, 0x1e, 0, 2, 1, Null, Null) \ + X(Neg, 0x1f, 0, 1, 1, Null, Null) \ + X(Not, 0x20, 0, 1, 1, Null, Null) \ + X(Or, 0x21, 0, 2, 1, Null, Null) \ + X(Plus, 0x22, 0, 2, 1, Null, Null) \ + X(PlusUConst, 0x23, 1, 1, 1, ULEB128, Null) \ + X(Shl, 0x24, 0, 2, 1, Null, Null) \ + X(Shr, 0x25, 0, 2, 1, Null, Null) \ + X(Shra, 0x26, 0, 2, 1, Null, Null) \ + X(Xor, 0x27, 0, 2, 1, Null, Null) \ + X(Bra, 0x28, 1, 1, 0, S16, Null) \ + X(Eq, 0x29, 0, 2, 1, Null, Null) \ + X(Ge, 0x2a, 0, 2, 1, Null, Null) \ + X(Gt, 0x2b, 0, 2, 1, Null, Null) \ + X(Le, 0x2c, 0, 2, 1, Null, Null) \ + X(Lt, 0x2d, 0, 2, 1, Null, Null) \ + X(Ne, 0x2e, 0, 2, 1, Null, Null) \ + X(Skip, 0x2f, 1, 0, 0, S16, Null) \ + X(Lit0, 0x30, 0, 0, 0, Null, Null) \ + X(Lit1, 0x31, 0, 0, 0, Null, Null) \ + X(Lit2, 0x32, 0, 0, 0, Null, Null) \ + X(Lit3, 0x33, 0, 0, 0, Null, Null) \ + X(Lit4, 0x34, 0, 0, 0, Null, Null) \ + X(Lit5, 0x35, 0, 0, 0, Null, Null) \ + X(Lit6, 0x36, 0, 0, 0, Null, Null) \ + X(Lit7, 0x37, 0, 0, 0, Null, Null) \ + X(Lit8, 0x38, 0, 0, 0, Null, Null) \ + X(Lit9, 0x39, 0, 0, 0, Null, Null) \ + X(Lit10, 0x3a, 0, 0, 0, Null, Null) \ + X(Lit11, 0x3b, 0, 0, 0, Null, Null) \ + X(Lit12, 0x3c, 0, 0, 0, Null, Null) \ + X(Lit13, 0x3d, 0, 0, 0, Null, Null) \ + X(Lit14, 0x3e, 0, 0, 0, Null, Null) \ + X(Lit15, 0x3f, 0, 0, 0, Null, Null) \ + X(Lit16, 0x40, 0, 0, 0, Null, Null) \ + X(Lit17, 0x41, 0, 0, 0, Null, Null) \ + X(Lit18, 0x42, 0, 0, 0, Null, Null) \ + X(Lit19, 0x43, 0, 0, 0, Null, Null) \ + X(Lit20, 0x44, 0, 0, 0, Null, Null) \ + X(Lit21, 0x45, 0, 0, 0, Null, Null) \ + X(Lit22, 0x46, 0, 0, 0, Null, Null) \ + X(Lit23, 0x47, 0, 0, 0, Null, Null) \ + X(Lit24, 0x48, 0, 0, 0, Null, Null) \ + X(Lit25, 0x49, 0, 0, 0, Null, Null) \ + X(Lit26, 0x4a, 0, 0, 0, Null, Null) \ + X(Lit27, 0x4b, 0, 0, 0, Null, Null) \ + X(Lit28, 0x4c, 0, 0, 0, Null, Null) \ + X(Lit29, 0x4d, 0, 0, 0, Null, Null) \ + X(Lit30, 0x4e, 0, 0, 0, Null, Null) \ + X(Lit31, 0x4f, 0, 0, 0, Null, Null) \ + X(Reg0, 0x50, 0, 0, 1, Null, Null) \ + X(Reg1, 0x51, 0, 0, 1, Null, Null) \ + X(Reg2, 0x52, 0, 0, 1, Null, Null) \ + X(Reg3, 0x53, 0, 0, 1, Null, Null) \ + X(Reg4, 0x54, 0, 0, 1, Null, Null) \ + X(Reg5, 0x55, 0, 0, 1, Null, Null) \ + X(Reg6, 0x56, 0, 0, 1, Null, Null) \ + X(Reg7, 0x57, 0, 0, 1, Null, Null) \ + X(Reg8, 0x58, 0, 0, 1, Null, Null) \ + X(Reg9, 0x59, 0, 0, 1, Null, Null) \ + X(Reg10, 0x5a, 0, 0, 1, Null, Null) \ + X(Reg11, 0x5b, 0, 0, 1, Null, Null) \ + X(Reg12, 0x5c, 0, 0, 1, Null, Null) \ + X(Reg13, 0x5d, 0, 0, 1, Null, Null) \ + X(Reg14, 0x5e, 0, 0, 1, Null, Null) \ + X(Reg15, 0x5f, 0, 0, 1, Null, Null) \ + X(Reg16, 0x60, 0, 0, 1, Null, Null) \ + X(Reg17, 0x61, 0, 0, 1, Null, Null) \ + X(Reg18, 0x62, 0, 0, 1, Null, Null) \ + X(Reg19, 0x63, 0, 0, 1, Null, Null) \ + X(Reg20, 0x64, 0, 0, 1, Null, Null) \ + X(Reg21, 0x65, 0, 0, 1, Null, Null) \ + X(Reg22, 0x66, 0, 0, 1, Null, Null) \ + X(Reg23, 0x67, 0, 0, 1, Null, Null) \ + X(Reg24, 0x68, 0, 0, 1, Null, Null) \ + X(Reg25, 0x69, 0, 0, 1, Null, Null) \ + X(Reg26, 0x6a, 0, 0, 1, Null, Null) \ + X(Reg27, 0x6b, 0, 0, 1, Null, Null) \ + X(Reg28, 0x6c, 0, 0, 1, Null, Null) \ + X(Reg29, 0x6d, 0, 0, 1, Null, Null) \ + X(Reg30, 0x6e, 0, 0, 1, Null, Null) \ + X(Reg31, 0x6f, 0, 0, 1, Null, Null) \ + X(BReg0, 0x70, 1, 0, 1, SLEB128, Null) \ + X(BReg1, 0x71, 1, 0, 1, SLEB128, Null) \ + X(BReg2, 0x72, 1, 0, 1, SLEB128, Null) \ + X(BReg3, 0x73, 1, 0, 1, SLEB128, Null) \ + X(BReg4, 0x74, 1, 0, 1, SLEB128, Null) \ + X(BReg5, 0x75, 1, 0, 1, SLEB128, Null) \ + X(BReg6, 0x76, 1, 0, 1, SLEB128, Null) \ + X(BReg7, 0x77, 1, 0, 1, SLEB128, Null) \ + X(BReg8, 0x78, 1, 0, 1, SLEB128, Null) \ + X(BReg9, 0x79, 1, 0, 1, SLEB128, Null) \ + X(BReg10, 0x7a, 1, 0, 1, SLEB128, Null) \ + X(BReg11, 0x7b, 1, 0, 1, SLEB128, Null) \ + X(BReg12, 0x7c, 1, 0, 1, SLEB128, Null) \ + X(BReg13, 0x7d, 1, 0, 1, SLEB128, Null) \ + X(BReg14, 0x7e, 1, 0, 1, SLEB128, Null) \ + X(BReg15, 0x7f, 1, 0, 1, SLEB128, Null) \ + X(BReg16, 0x80, 1, 0, 1, SLEB128, Null) \ + X(BReg17, 0x81, 1, 0, 1, SLEB128, Null) \ + X(BReg18, 0x82, 1, 0, 1, SLEB128, Null) \ + X(BReg19, 0x83, 1, 0, 1, SLEB128, Null) \ + X(BReg20, 0x84, 1, 0, 1, SLEB128, Null) \ + X(BReg21, 0x85, 1, 0, 1, SLEB128, Null) \ + X(BReg22, 0x86, 1, 0, 1, SLEB128, Null) \ + X(BReg23, 0x87, 1, 0, 1, SLEB128, Null) \ + X(BReg24, 0x88, 1, 0, 1, SLEB128, Null) \ + X(BReg25, 0x89, 1, 0, 1, SLEB128, Null) \ + X(BReg26, 0x8a, 1, 0, 1, SLEB128, Null) \ + X(BReg27, 0x8b, 1, 0, 1, SLEB128, Null) \ + X(BReg28, 0x8c, 1, 0, 1, SLEB128, Null) \ + X(BReg29, 0x8d, 1, 0, 1, SLEB128, Null) \ + X(BReg30, 0x8e, 1, 0, 1, SLEB128, Null) \ + X(BReg31, 0x8f, 1, 0, 1, SLEB128, Null) \ + X(RegX, 0x90, 1, 0, 1, ULEB128, Null) \ + X(FBReg, 0x91, 1, 0, 1, SLEB128, Null) \ + X(BRegX, 0x92, 2, 0, 1, ULEB128, SLEB128) \ + X(Piece, 0x93, 1, 0, 0, ULEB128, Null) \ + X(DerefSize, 0x94, 1, 1, 1, U8, Null) \ + X(XDerefSize, 0x95, 1, 2, 1, U8, Null) \ + X(Nop, 0x96, 0, 0, 0, Null, Null) \ + X(PushObjectAddress, 0x97, 0, 0, 1, Null, Null) \ + X(Call2, 0x98, 1, 0, 0, U16, Null) \ + X(Call4, 0x99, 1, 0, 0, U32, Null) \ + X(CallRef, 0x9a, 1, 0, 0, DwarfUInt,Null) \ + X(FormTlsAddress, 0x9b, 0, 0, 1, Null, Null) \ + X(CallFrameCfa, 0x9c, 0, 0, 1, Null, Null) \ + X(BitPiece, 0x9d, 2, 0, 0, ULEB128, ULEB128) -#define DW_Expr_V5_XList(X) \ -X(ImplicitPointer, 0xa0, 2, 0, 1) \ -X(Addrx, 0xa1, 1, 0, 1) \ -X(Constx, 0xa2, 1, 0, 1) \ -X(EntryValue, 0xa3, 2, 0, 0) \ -X(ConstType, 0xa4, 3, 0, 1) \ -X(RegvalType, 0xa5, 2, 0, 1) \ -X(DerefType, 0xa6, 2, 1, 1) \ -X(XDerefType, 0xa7, 2, 2, 1) \ -X(Convert, 0xa8, 1, 1, 1) \ -X(Reinterpret, 0xa9, 1, 1, 1) +#define DW_Expr_V4_XList \ + X(ImplicitValue, 0x9e, 2, 0, 1, Block, Null) \ + X(StackValue, 0x9f, 0, 0, 0, Null, Null) -#define DW_Expr_GNU_XList(X) \ -X(GNU_PushTlsAddress, 0xe0, 0, 0, 1) \ -X(GNU_UnInit, 0xf0, 0, 0, 0) \ -X(GNU_ImplicitPointer, 0xf2, 2, 0, 1) \ -X(GNU_EntryValue, 0xf3, 2, 0, 0) \ -X(GNU_ConstType, 0xf4, 3, 0, 1) \ -X(GNU_RegvalType, 0xf5, 2, 0, 1) \ -X(GNU_DerefType, 0xf6, 2, 1, 1) \ -X(GNU_Convert, 0xf7, 1, 1, 1) \ -X(GNU_ParameterRef, 0xfa, 1, 0, 0) \ -X(GNU_AddrIndex, 0xfb, 0, 0, 1) \ -X(GNU_ConstIndex, 0xfc, 1, 0, 1) +#define DW_Expr_V5_XList \ + X(ImplicitPointer, 0xa0, 2, 0, 1, DwarfUInt, SLEB128) \ + X(Addrx, 0xa1, 1, 0, 1, ULEB128, Null) \ + X(Constx, 0xa2, 1, 0, 1, ULEB128, Null) \ + X(EntryValue, 0xa3, 1, 0, 0, Block, Null) \ + X(ConstType, 0xa4, 2, 0, 1, ULEB128, Block) \ + X(RegvalType, 0xa5, 2, 0, 1, ULEB128, ULEB128) \ + X(DerefType, 0xa6, 2, 1, 1, U8, ULEB128) \ + X(XDerefType, 0xa7, 2, 2, 1, U8, ULEB128) \ + X(Convert, 0xa8, 1, 1, 1, ULEB128, Null) \ + X(Reinterpret, 0xa9, 1, 1, 1, ULEB128, Null) + +#define DW_Expr_GNU_XList \ + X(GNU_PushTlsAddress, 0xe0, 0, 0, 1, Null, Null) \ + X(GNU_UnInit, 0xf0, 0, 0, 0, Null, Null) \ + X(GNU_ImplicitPointer, 0xf2, 2, 0, 1, DwarfUInt, SLEB128) \ + X(GNU_EntryValue, 0xf3, 1, 0, 0, Block, Null) \ + X(GNU_ConstType, 0xf4, 2, 0, 1, ULEB128, Block) \ + X(GNU_RegvalType, 0xf5, 2, 0, 1, ULEB128, ULEB128) \ + X(GNU_DerefType, 0xf6, 2, 1, 1, U8, ULEB128) \ + X(GNU_Convert, 0xf7, 1, 1, 1, ULEB128, Null) \ + X(GNU_ParameterRef, 0xfa, 1, 0, 0, U32, Null) \ + X(GNU_AddrIndex, 0xfb, 0, 0, 1, Null, Null) \ + X(GNU_ConstIndex, 0xfc, 1, 0, 1, ULEB128, Null) typedef U8 DW_ExprOp; typedef enum DW_ExprOpEnum { -#define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT) DW_ExprOp_##_N = _ID, - DW_Expr_V3_XList(X) - DW_Expr_V4_XList(X) - DW_Expr_V5_XList(X) - DW_Expr_GNU_XList(X) +#define X(_N, _ID, _OPER_COUNT, _POP_COUNT, _PUSH_COUNT, ...) DW_ExprOp_##_N = _ID, + DW_Expr_V3_XList + DW_Expr_V4_XList + DW_Expr_V5_XList + DW_Expr_GNU_XList #undef X } DW_ExprOpEnum; @@ -1745,9 +1763,10 @@ internal DW_AttribClass dw_pick_attrib_value_class(DW_Version ver, DW_Ext ext, B internal U64 dw_pick_default_lower_bound(DW_Language lang); -internal U64 dw_operand_count_from_expr_op(DW_ExprOp op); -internal U64 dw_pop_count_from_expr_op(DW_ExprOp op); -internal U64 dw_push_count_from_expr_op(DW_ExprOp op); +internal U64 dw_operand_count_from_expr_op(DW_ExprOp op); +internal U64 dw_pop_count_from_expr_op(DW_ExprOp op); +internal U64 dw_push_count_from_expr_op(DW_ExprOp op); +internal DW_ExprOperandType * dw_operand_types_from_expr_opcode(DW_ExprOp op); //////////////////////////////// //~ CFA diff --git a/src/dwarf/dwarf_expr.c b/src/dwarf/dwarf_expr.c index fb824763..f81afa4c 100644 --- a/src/dwarf/dwarf_expr.c +++ b/src/dwarf/dwarf_expr.c @@ -1417,3 +1417,104 @@ exit:; return result; } +internal String8 +dw_encode_expr(Arena *arena, DW_Format format, U64 addr_size, DW_ExprEnc *encs, U64 encs_count) +{ + Temp scratch = scratch_begin(&arena, 1); + String8List *srl = push_array(scratch.arena, String8List, 1); + str8_serial_begin(scratch.arena, srl); + + for EachIndex(i, encs_count) { + DW_ExprEnc *e = &encs[i]; + + switch (e->type) { + case DW_ExprEncType_Op: { + str8_serial_push_struct(scratch.arena, srl, &e->op); + } break; + case DW_ExprEncType_U8: { + str8_serial_push_struct(scratch.arena, srl, &e->u8); + } break; + case DW_ExprEncType_U16: { + str8_serial_push_struct(scratch.arena, srl, &e->u16); + } break; + case DW_ExprEncType_U32: { + str8_serial_push_struct(scratch.arena, srl, &e->u32); + } break; + case DW_ExprEncType_U64: { + str8_serial_push_struct(scratch.arena, srl, &e->u64); + } break; + case DW_ExprEncType_S8: { + str8_serial_push_struct(scratch.arena, srl, &e->s8); + } break; + case DW_ExprEncType_S16: { + str8_serial_push_struct(scratch.arena, srl, &e->s16); + } break; + case DW_ExprEncType_S32: { + str8_serial_push_struct(scratch.arena, srl, &e->s32); + } break; + case DW_ExprEncType_S64: { + str8_serial_push_struct(scratch.arena, srl, &e->s64); + } break; + case DW_ExprEncType_ULEB128: { + U64 buffer_size = 0; + U8 buffer[10]; + for (U64 value = e->u64; value != 0; ) { + U8 byte = value & 0x7f; + value >>= 7; + if (value != 0) { + byte |= 0x80; + } + Assert(buffer_size < sizeof(buffer)); + buffer[buffer_size++] = byte; + } + str8_serial_push_string(scratch.arena, srl, str8(buffer, buffer_size)); + } break; + case DW_ExprEncType_SLEB128: { + U64 buffer_size = 0; + U8 buffer[10]; + for (S64 value = e->s64, more = 1; more != 0; ) { + U8 byte = value & 0x7f; + value >>= 7; + U8 sign_bit = byte & 0x40; + if ((value == 0 && sign_bit == 0) || (value == -1 && sign_bit != 0)) { + more = 0; + } else { + byte |= 0x80; + } + Assert(buffer_size < sizeof(buffer)); + buffer[buffer_size++] = byte; + } + str8_serial_push_string(scratch.arena, srl, str8(buffer, buffer_size)); + } break; + case DW_ExprEncType_Addr: { + Assert(addr_size <= sizeof(e->addr)); + str8_serial_push_string(scratch.arena, srl, str8((U8 *)&e->addr, addr_size)); + } break; + case DW_ExprEncType_Block: { + Assert(e->block.size <= max_U8); + str8_serial_push_u8(scratch.arena, srl, (U8)e->block.size); + str8_serial_push_string(scratch.arena, srl, e->block); + } break; + case DW_ExprEncType_DwarfUInt: { + switch (format) { + case DW_Format_Null: {} break; + case DW_Format_32Bit: { str8_serial_push_u32(scratch.arena, srl, e->u32); } break; + case DW_Format_64Bit: { str8_serial_push_u64(scratch.arena, srl, e->u64); } break; + default: { InvalidPath; } break; + } + } break; + case DW_ExprEncType_Label: { + // TODO: + } break; + case DW_ExprEncType_DeclLabel: { + // TODO: + } break; + default: { InvalidPath; } break; + } + } + + String8 expr = str8_serial_end(arena, srl); + scratch_end(scratch); + return expr; +} + diff --git a/src/dwarf/dwarf_expr.h b/src/dwarf/dwarf_expr.h index d9d3f0c7..c1ac240f 100644 --- a/src/dwarf/dwarf_expr.h +++ b/src/dwarf/dwarf_expr.h @@ -4,6 +4,9 @@ #ifndef DWARF_EXPR_H #define DWARF_EXPR_H +//////////////////////////////// +// evaluator + typedef struct DW_ExprContext { Arch arch; @@ -115,6 +118,66 @@ typedef struct DW_ExprResult int x; } DW_ExprResult; +//////////////////////////////// +// encoder + +typedef enum +{ + DW_ExprEncType_Null, + DW_ExprEncType_Op, + DW_ExprEncType_U8, + DW_ExprEncType_U16, + DW_ExprEncType_U32, + DW_ExprEncType_U64, + DW_ExprEncType_S8, + DW_ExprEncType_S16, + DW_ExprEncType_S32, + DW_ExprEncType_S64, + DW_ExprEncType_ULEB128, + DW_ExprEncType_SLEB128, + DW_ExprEncType_Addr, + DW_ExprEncType_Block, + DW_ExprEncType_DwarfUInt, + DW_ExprEncType_Label, + DW_ExprEncType_DeclLabel, +} DW_ExprEncType; + +typedef struct DW_ExprEnc +{ + DW_ExprEncType type; + union { + DW_ExprOp op; + U8 u8; + U16 u16; + U32 u32; + U64 u64; + S8 s8; + S16 s16; + S32 s32; + S64 s64; + U64 addr; + String8 block; + char *label; + }; +} DW_ExprEnc; + +#define DW_ExprEnc_Op(v) { .type = DW_ExprEncType_Op, .op = DW_ExprOp_##v } +#define DW_ExprEnc_U8(v) { .type = DW_ExprEncType_U8, .u8 = v } +#define DW_ExprEnc_U16(v) { .type = DW_ExprEncType_U16, .u16 = v } +#define DW_ExprEnc_U32(v) { .type = DW_ExprEncType_U32, .u32 = v } +#define DW_ExprEnc_U64(v) { .type = DW_ExprEncType_U64, .u64 = v } +#define DW_ExprEnc_S8(v) { .type = DW_ExprEncType_S8, .s8 = v } +#define DW_ExprEnc_S16(v) { .type = DW_ExprEncType_S16, .s16 = v } +#define DW_ExprEnc_S32(v) { .type = DW_ExprEncType_S32, .s32 = v } +#define DW_ExprEnc_S64(v) { .type = DW_ExprEncType_S64, .s64 = v } +#define DW_ExprEnc_ULEB128(v) { .type = DW_ExprEncType_ULEB128, .u64 = v } +#define DW_ExprEnc_SLEB128(v) { .type = DW_ExprEncType_SLEB128, .s64 = v } +#define DW_ExprEnc_Addr(v) { .type = DW_ExprEncType_Addr, .addr = v } +#define DW_ExprEnc_Block(v) { .type = DW_ExprEncType_Block, .block = v } +#define DW_ExprEnc_UInt(v) { .type = DW_ExprEncType_DwarfUInt, .u64 = v } +#define DW_ExprEnc_Label(v) { .type = DW_ExprEncType_Label, .label = v } +#define DW_ExprEnc_DeclLabel(v) { .type = DW_ExprEncType_DeclLabel, .label = v } + //////////////////////////////// // pieces @@ -174,5 +237,8 @@ internal String8 dw_string_from_expr_value(Arena *arena, U64 addr_size, DW_ExprV // evaluator internal DW_UnwindStatus dw_eval_expr(Arena *arena, DW_ExprContext *ctx, DW_Expr expr, DW_RegRead *reg_read, void *reg_read_ud, DW_ExprValue *value_out); +// encoder +internal String8 dw_encode_expr(Arena *arena, DW_Format format, U64 addr_size, DW_ExprEnc *encs, U64 encs_count); + #endif //DWARF_EXPR_H diff --git a/src/dwarf/dwarf_parse.c b/src/dwarf/dwarf_parse.c index 8559b08d..3e2a4a1b 100644 --- a/src/dwarf/dwarf_parse.c +++ b/src/dwarf/dwarf_parse.c @@ -3116,210 +3116,59 @@ internal DW_Expr dw_expr_from_data(Arena *arena, DW_Format format, U64 addr_size, String8 data) { DW_Expr expr = {0}; - for (U64 cursor = 0; cursor < data.size; ) { - U64 inst_start = cursor; - + for (U64 cursor = 0, inst_start = 0; cursor < data.size; inst_start = cursor) { + // read opcode DW_ExprOp opcode = 0; - cursor += str8_deserial_read_struct(data, cursor, &opcode); + U64 opcode_size = str8_deserial_read_struct(data, cursor, &opcode); + if (opcode_size == 0) { break; } + cursor += opcode_size; - DW_ExprOperand operands[4] = {0}; - switch (opcode) { - case DW_ExprOp_Lit0: case DW_ExprOp_Lit1: case DW_ExprOp_Lit2: - case DW_ExprOp_Lit3: case DW_ExprOp_Lit4: case DW_ExprOp_Lit5: - case DW_ExprOp_Lit6: case DW_ExprOp_Lit7: case DW_ExprOp_Lit8: - case DW_ExprOp_Lit9: case DW_ExprOp_Lit10: case DW_ExprOp_Lit11: - case DW_ExprOp_Lit12: case DW_ExprOp_Lit13: case DW_ExprOp_Lit14: - case DW_ExprOp_Lit15: case DW_ExprOp_Lit16: case DW_ExprOp_Lit17: - case DW_ExprOp_Lit18: case DW_ExprOp_Lit19: case DW_ExprOp_Lit20: - case DW_ExprOp_Lit21: case DW_ExprOp_Lit22: case DW_ExprOp_Lit23: - case DW_ExprOp_Lit24: case DW_ExprOp_Lit25: case DW_ExprOp_Lit26: - case DW_ExprOp_Lit27: case DW_ExprOp_Lit28: case DW_ExprOp_Lit29: - case DW_ExprOp_Lit30: case DW_ExprOp_Lit31: { - // implicit operands - } break; - case DW_ExprOp_Const1U: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); } break; - case DW_ExprOp_Const2U: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u16); } break; - case DW_ExprOp_Const4U: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u32); } break; - case DW_ExprOp_Const8U: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].u64); } break; - case DW_ExprOp_Const1S: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s8); } break; - case DW_ExprOp_Const2S: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s16); } break; - case DW_ExprOp_Const4S: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s32); } break; - case DW_ExprOp_Const8S: { cursor += str8_deserial_read_struct(data, cursor, &operands[0].s64); } break; - case DW_ExprOp_ConstU: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); } break; - case DW_ExprOp_ConstS: { cursor += str8_deserial_read_sleb128(data, cursor, &operands[0].s64); } break; - case DW_ExprOp_Addr: { cursor += str8_deserial_read(data, cursor, &operands[0].u64, addr_size, addr_size); } break; - case DW_ExprOp_Reg0: case DW_ExprOp_Reg1: case DW_ExprOp_Reg2: - case DW_ExprOp_Reg3: case DW_ExprOp_Reg4: case DW_ExprOp_Reg5: - case DW_ExprOp_Reg6: case DW_ExprOp_Reg7: case DW_ExprOp_Reg8: - case DW_ExprOp_Reg9: case DW_ExprOp_Reg10: case DW_ExprOp_Reg11: - case DW_ExprOp_Reg12: case DW_ExprOp_Reg13: case DW_ExprOp_Reg14: - case DW_ExprOp_Reg15: case DW_ExprOp_Reg16: case DW_ExprOp_Reg17: - case DW_ExprOp_Reg18: case DW_ExprOp_Reg19: case DW_ExprOp_Reg20: - case DW_ExprOp_Reg21: case DW_ExprOp_Reg22: case DW_ExprOp_Reg23: - case DW_ExprOp_Reg24: case DW_ExprOp_Reg25: case DW_ExprOp_Reg26: - case DW_ExprOp_Reg27: case DW_ExprOp_Reg28: case DW_ExprOp_Reg29: - case DW_ExprOp_Reg30: case DW_ExprOp_Reg31: { - // implicit operands - } break; - case DW_ExprOp_RegX: { cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); } break; - case DW_ExprOp_ImplicitValue: { - U64 value_size = 0; String8 value = {0}; - cursor += str8_deserial_read_uleb128(data, cursor, &value_size); - cursor += str8_deserial_read_block(data, cursor, value_size, &operands[0].block); - } break; - case DW_ExprOp_Piece: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - } break; - case DW_ExprOp_BitPiece: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - cursor += str8_deserial_read_uleb128(data, cursor, &operands[1].u64); - } break; - case DW_ExprOp_Pick: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); - } break; - case DW_ExprOp_PlusUConst: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - } break; - case DW_ExprOp_Skip: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].s16); - } break; - case DW_ExprOp_Bra: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].s16); - } break; - case DW_ExprOp_BReg0: case DW_ExprOp_BReg1: case DW_ExprOp_BReg2: - case DW_ExprOp_BReg3: case DW_ExprOp_BReg4: case DW_ExprOp_BReg5: - case DW_ExprOp_BReg6: case DW_ExprOp_BReg7: case DW_ExprOp_BReg8: - case DW_ExprOp_BReg9: case DW_ExprOp_BReg10: case DW_ExprOp_BReg11: - case DW_ExprOp_BReg12: case DW_ExprOp_BReg13: case DW_ExprOp_BReg14: - case DW_ExprOp_BReg15: case DW_ExprOp_BReg16: case DW_ExprOp_BReg17: - case DW_ExprOp_BReg18: case DW_ExprOp_BReg19: case DW_ExprOp_BReg20: - case DW_ExprOp_BReg21: case DW_ExprOp_BReg22: case DW_ExprOp_BReg23: - case DW_ExprOp_BReg24: case DW_ExprOp_BReg25: case DW_ExprOp_BReg26: - case DW_ExprOp_BReg27: case DW_ExprOp_BReg28: case DW_ExprOp_BReg29: - case DW_ExprOp_BReg30: case DW_ExprOp_BReg31: { - cursor += str8_deserial_read_sleb128(data, cursor, &operands[0].s64); - } break; - case DW_ExprOp_BRegX: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - cursor += str8_deserial_read_sleb128(data, cursor, &operands[1].s64); - } break; - case DW_ExprOp_FBReg: { - cursor += str8_deserial_read_sleb128(data, cursor, &operands[0].s64); - } break; - case DW_ExprOp_Deref: { - // no operands - } break; - case DW_ExprOp_DerefSize: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); - } break; - case DW_ExprOp_XDerefSize: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); - } break; - case DW_ExprOp_Call2: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].u16); - } break; - case DW_ExprOp_Call4: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].u32); - } break; - case DW_ExprOp_CallRef: { - cursor += str8_deserial_read_dwarf_uint(data, cursor, format, &operands[0].u64); - } break; - case DW_ExprOp_ImplicitPointer: - case DW_ExprOp_GNU_ImplicitPointer: { - cursor += str8_deserial_read_dwarf_uint(data, cursor, format, &operands[0].u64); - cursor += str8_deserial_read_sleb128(data, cursor, &operands[1].s64); - } break; - case DW_ExprOp_Convert: - case DW_ExprOp_GNU_Convert: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - } break; - case DW_ExprOp_GNU_ParameterRef: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].u32); - } break; - case DW_ExprOp_DerefType: - case DW_ExprOp_GNU_DerefType: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); - cursor += str8_deserial_read_uleb128(data, cursor, &operands[1].u64); - } break; - case DW_ExprOp_XDerefType: { - cursor += str8_deserial_read_struct(data, cursor, &operands[0].u8); - cursor += str8_deserial_read_uleb128(data, cursor, &operands[1].u64); - } break; - case DW_ExprOp_ConstType: - case DW_ExprOp_GNU_ConstType: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - cursor += str8_deserial_read_struct(data, cursor, &operands[1].u8); - cursor += str8_deserial_read_block(data, cursor, operands[1].u8, &operands[2].block); - } break; - case DW_ExprOp_RegvalType: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - cursor += str8_deserial_read_uleb128(data, cursor, &operands[1].u64); - } break; - case DW_ExprOp_EntryValue: - case DW_ExprOp_GNU_EntryValue: { - U64 entry_value_expr_size = 0; - cursor += str8_deserial_read_uleb128(data, cursor, &entry_value_expr_size); - cursor += str8_deserial_read_block(data, cursor, entry_value_expr_size, &operands[0].block); - } break; - case DW_ExprOp_Addrx: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - } break; - case DW_ExprOp_Constx: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - } break; - case DW_ExprOp_CallFrameCfa: - case DW_ExprOp_FormTlsAddress: - case DW_ExprOp_PushObjectAddress: - case DW_ExprOp_Nop: - case DW_ExprOp_Eq: - case DW_ExprOp_Ge: - case DW_ExprOp_Gt: - case DW_ExprOp_Le: - case DW_ExprOp_Lt: - case DW_ExprOp_Ne: - case DW_ExprOp_Shl: - case DW_ExprOp_Shr: - case DW_ExprOp_Shra: - case DW_ExprOp_Xor: - case DW_ExprOp_XDeref: - case DW_ExprOp_Abs: - case DW_ExprOp_And: - case DW_ExprOp_Div: - case DW_ExprOp_Minus: - case DW_ExprOp_Mod: - case DW_ExprOp_Mul: - case DW_ExprOp_Neg: - case DW_ExprOp_Not: - case DW_ExprOp_Or: - case DW_ExprOp_Plus: - case DW_ExprOp_Rot: - case DW_ExprOp_Swap: - case DW_ExprOp_Dup: - case DW_ExprOp_Drop: - case DW_ExprOp_Over: - case DW_ExprOp_StackValue: - case DW_ExprOp_GNU_PushTlsAddress: { - // no operands - } break; - case DW_ExprOp_GNU_AddrIndex: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - } break; - case DW_ExprOp_GNU_ConstIndex: { - cursor += str8_deserial_read_uleb128(data, cursor, &operands[0].u64); - } break; - default: { InvalidPath; } break; + // read operands + U64 operand_count = dw_operand_count_from_expr_op(opcode); + DW_ExprOperandType *operand_types = dw_operand_types_from_expr_opcode(opcode); + DW_ExprOperand operands[2] = {0}; + for EachIndex(operand_idx, operand_count) { + U64 operand_size = 0; + switch (operand_types[operand_idx]) { + case DW_ExprOperandType_Null: { } break; + case DW_ExprOperandType_U8: { operand_size = str8_deserial_read_struct(data, cursor, &operands[operand_idx].u8); } break; + case DW_ExprOperandType_U16: { operand_size = str8_deserial_read_struct(data, cursor, &operands[operand_idx].u16); } break; + case DW_ExprOperandType_U32: { operand_size = str8_deserial_read_struct(data, cursor, &operands[operand_idx].u32); } break; + case DW_ExprOperandType_U64: { operand_size = str8_deserial_read_struct(data, cursor, &operands[operand_idx].u64); } break; + case DW_ExprOperandType_S8: { operand_size = str8_deserial_read_struct(data, cursor, &operands[operand_idx].s8); } break; + case DW_ExprOperandType_S16: { operand_size = str8_deserial_read_struct(data, cursor, &operands[operand_idx].s16); } break; + case DW_ExprOperandType_S32: { operand_size = str8_deserial_read_struct(data, cursor, &operands[operand_idx].s32); } break; + case DW_ExprOperandType_S64: { operand_size = str8_deserial_read_struct(data, cursor, &operands[operand_idx].s64); } break; + case DW_ExprOperandType_ULEB128: { operand_size = str8_deserial_read_uleb128(data, cursor, &operands[operand_idx].u64); } break; + case DW_ExprOperandType_SLEB128: { operand_size = str8_deserial_read_sleb128(data, cursor, &operands[operand_idx].s64); } break; + case DW_ExprOperandType_Addr: { operand_size = str8_deserial_read(data, cursor, &operands[operand_idx].u64, addr_size, addr_size); } break; + case DW_ExprOperandType_DwarfUInt: { operand_size = str8_deserial_read_dwarf_uint(data, cursor, format, &operands[operand_idx].u64); } break; + case DW_ExprOperandType_Block: { + U8 block_size; + U64 block_size_size = str8_deserial_read_struct(data, cursor, &block_size); + U64 block_read_size = str8_deserial_read_block(data, cursor + block_size_size, block_size, &operands[operand_idx].block); + if(block_read_size == block_size_size) { + operand_size = block_size_size + block_read_size; + } + } break; + default: { InvalidPath; } break; + } + if (operand_size == 0) { goto exit; } + cursor += operand_size; } - U64 operand_count = dw_operand_count_from_expr_op(opcode); + // fill out instruction DW_ExprInst *inst = push_array(arena, DW_ExprInst, 1); inst->opcode = opcode; inst->size = cursor - inst_start; inst->operands = push_array(arena, DW_ExprOperand, operand_count); MemoryCopy(inst->operands, operands, operand_count * sizeof(DW_ExprOperand)); + // push instruction DLLPushBack(expr.first, expr.last, inst); expr.count += 1; } +exit:; return expr; } diff --git a/src/torture/dwarf_expr_test.c b/src/torture/dwarf_expr_test.c new file mode 100644 index 00000000..5035d0a2 --- /dev/null +++ b/src/torture/dwarf_expr_test.c @@ -0,0 +1,49 @@ +// Copyright (c) Epic Games Tools +// Licensed under the MIT license (https://opensource.org/license/mit/) + +#define BUILD_CONSOLE_INFERFACE 1 +#define BUILD_TITLE "DWARF Expr Test" + +//////////////////////////////// + +#include "third_party/xxHash/xxhash.c" +#include "third_party/xxHash/xxhash.h" +#include "third_party/radsort/radsort.h" + +//////////////////////////////// + +#include "base/base_inc.h" +#include "os/os_inc.h" +#include "linker/hash_table.h" +#include "coff/coff.h" +#include "elf/elf.h" +#include "elf/elf_parse.h" +#include "dwarf/dwarf_inc.h" + +#include "base/base_inc.c" +#include "os/os_inc.c" +#include "coff/coff.c" +#include "elf/elf.c" +#include "elf/elf_parse.c" +#include "linker/hash_table.c" +#include "dwarf/dwarf_inc.c" + +//////////////////////////////// + +internal void +entry_point(CmdLine *cmdline) +{ + Temp scratch = scratch_begin(0, 0); + + { + DW_ExprEnc program[] = { + DW_ExprEnc_DeclLabel("foo"), + DW_ExprEnc_Op(BReg11), DW_ExprEnc_S64(44), + DW_ExprEnc_Op(Skip), DW_ExprEnc_Label("foo"), + }; + String8 expr_data = dw_encode_expr(scratch.arena, DW_Format_64Bit, sizeof(U64), program, ArrayCount(program)); + } + + scratch_end(scratch); +} +