|
|
/*** unasm.c - Unassemble AML back to ASL
* * Copyright (c) 1996,1998 Microsoft Corporation * Author: Michael Tsang (MikeTs) * Created: 10/01/97 * * MODIFICATION HISTORY */
#include "pch.h"
//Local function prototype
VOID LOCAL Indent(PUCHAR pbOp, int iLevel); UCHAR LOCAL FindOpClass(UCHAR bOp, POPMAP pOpTable); PASLTERM LOCAL FindOpTerm(ULONG dwOpcode); PASLTERM LOCAL FindKeywordTerm(char cKWGroup, UCHAR bData); LONG LOCAL UnAsmOpcode(PUCHAR *ppbOp); LONG LOCAL UnAsmDataObj(PUCHAR *ppbOp); LONG LOCAL UnAsmNameObj(PUCHAR *ppbOp, PNSOBJ pns, char c); LONG LOCAL UnAsmNameTail(PUCHAR *ppbOp, PSZ pszBuff, int iLen); LONG LOCAL UnAsmTermObj(PASLTERM pterm, PUCHAR *ppbOp); LONG LOCAL UnAsmArgs(PSZ pszUnAsmArgTypes, PSZ pszArgActions, PUCHAR *ppbOp, PNSOBJ pns); LONG LOCAL UnAsmSuperName(PUCHAR *ppbOp); LONG LOCAL UnAsmDataList(PUCHAR *ppbOp, PUCHAR pbEnd); LONG LOCAL UnAsmPkgList(PUCHAR *ppbOp, PUCHAR pbEnd); LONG LOCAL UnAsmFieldList(PUCHAR *ppbOp, PUCHAR pbEnd); LONG LOCAL UnAsmField(PUCHAR *ppbOp, PULONG pdwBitPos);
/***LP UnAsmScope - Unassemble a scope
* * ENTRY * ppbOp -> Current Opcode pointer * pbEnd -> end of scope * uipbOp - Op address * pnsScope - Scope object * iLevel - level of indentation * icLines - 1: unasm one line; 0: unasm all; -1: internal * * EXIT-SUCCESS * returns UNASMERR_NONE * EXIT-FAILURE * returns negative error code */
LONG LOCAL UnAsmScope(PUCHAR *ppbOp, PUCHAR pbEnd, ULONG_PTR uipbOp, PNSOBJ pnsScope, int iLevel, int icLines) { LONG rc = UNASMERR_NONE; int icLinesLeft = icLines;
if (uipbOp != 0) { guipbOpXlate = uipbOp - (ULONG_PTR)(*ppbOp); }
if (pnsScope != NULL) { gpnsCurUnAsmScope = pnsScope; }
if (iLevel != -1) { giLevel = iLevel; }
if (icLines < 0) { Indent(*ppbOp, giLevel); PRINTF("{"); giLevel++; } else if (icLines == 0) { icLinesLeft = -1; }
while (*ppbOp < pbEnd) { Indent(*ppbOp, giLevel);
if ((rc = UnAsmOpcode(ppbOp)) == UNASMERR_NONE) { if (icLinesLeft < 0) { continue; }
if (--icLinesLeft == 0) { break; } } else { break; } }
if ((rc == UNASMERR_NONE) && (icLines < 0)) { giLevel--; Indent(*ppbOp, giLevel); PRINTF("}"); }
return rc; } //UnAsmScope
/***LP Indent - Print indent level
* * ENTRY * pbOp -> opcode * iLevel - indent level * * EXIT * None */
VOID LOCAL Indent(PUCHAR pbOp, int iLevel) { int i;
PRINTF("\n%08x: ", pbOp + guipbOpXlate); for (i = 0; i < iLevel; ++i) { PRINTF("| "); } } //Indent
/***LP FindOpClass - Find opcode class of extended opcode
* * ENTRY * bOp - opcode * pOpTable -> opcode table * * EXIT-SUCCESS * returns opcode class * EXIT-FAILURE * returns OPCLASS_INVALID */
UCHAR LOCAL FindOpClass(UCHAR bOp, POPMAP pOpTable) { UCHAR bOpClass = OPCLASS_INVALID;
while (pOpTable->bOpClass != 0) { if (bOp == pOpTable->bExOp) { bOpClass = pOpTable->bOpClass; break; } else { pOpTable++; } }
return bOpClass; } //FindOpClass
/***LP FindOpTerm - Find opcode in TermTable
* * ENTRY * dwOpcode - opcode * * EXIT-SUCCESS * returns TermTable entry pointer * EXIT-FAILURE * returns NULL */
PASLTERM LOCAL FindOpTerm(ULONG dwOpcode) { PASLTERM pterm = NULL; int i;
for (i = 0; TermTable[i].pszID != NULL; ++i) { if ((TermTable[i].dwOpcode == dwOpcode) && (TermTable[i].dwfTermClass & (UTC_CONST_NAME | UTC_SHORT_NAME | UTC_NAMESPACE_MODIFIER | UTC_DATA_OBJECT | UTC_NAMED_OBJECT | UTC_OPCODE_TYPE1 | UTC_OPCODE_TYPE2))) { break; } }
if (TermTable[i].pszID != NULL) { pterm = &TermTable[i]; }
return pterm; } //FindOpTerm
/***LP FindKeywordTerm - Find keyword in TermTable
* * ENTRY * cKWGroup - keyword group * bData - data to match keyword * * EXIT-SUCCESS * returns TermTable entry pointer * EXIT-FAILURE * returns NULL */
PASLTERM LOCAL FindKeywordTerm(char cKWGroup, UCHAR bData) { PASLTERM pterm = NULL; int i;
for (i = 0; TermTable[i].pszID != NULL; ++i) { if ((TermTable[i].dwfTermClass == UTC_KEYWORD) && (TermTable[i].pszArgActions[0] == cKWGroup) && ((bData & (UCHAR)(TermTable[i].dwTermData >> 8)) == (UCHAR)(TermTable[i].dwTermData & 0xff))) { break; } }
if (TermTable[i].pszID != NULL) { pterm = &TermTable[i]; }
return pterm; } //FindKeywordTerm
/***LP UnAsmOpcode - Unassemble an Opcode
* * ENTRY * ppbOp -> Opcode pointer * * EXIT-SUCCESS * returns UNASMERR_NONE * EXIT-FAILURE * returns negative error code */
LONG LOCAL UnAsmOpcode(PUCHAR *ppbOp) { LONG rc = UNASMERR_NONE; ULONG dwOpcode; UCHAR bOp; PASLTERM pterm; char szUnAsmArgTypes[MAX_ARGS + 1]; int i;
if (**ppbOp == OP_EXT_PREFIX) { (*ppbOp)++; dwOpcode = (((ULONG)**ppbOp) << 8) | OP_EXT_PREFIX; bOp = FindOpClass(**ppbOp, ExOpClassTable); } else { dwOpcode = (ULONG)(**ppbOp); bOp = OpClassTable[**ppbOp]; }
switch (bOp) { case OPCLASS_DATA_OBJ: rc = UnAsmDataObj(ppbOp); break;
case OPCLASS_NAME_OBJ: { NSOBJ NSObj = {0};
if (((rc = UnAsmNameObj(ppbOp, &NSObj, NSTYPE_UNKNOWN)) == UNASMERR_NONE) && (NSObj.ObjData.dwDataType == OBJTYPE_METHOD)) { PMETHODOBJ pm = (PMETHODOBJ)GetObjBuff(&NSObj.ObjData); int iNumArgs;
if (pm != NULL) { iNumArgs = pm->bMethodFlags & METHOD_NUMARG_MASK;
for (i = 0; i < iNumArgs; ++i) { szUnAsmArgTypes[i] = 'C'; } szUnAsmArgTypes[i] = '\0'; rc = UnAsmArgs(szUnAsmArgTypes, NULL, ppbOp, NULL); LocalFree(pm); } } break; } case OPCLASS_ARG_OBJ: case OPCLASS_LOCAL_OBJ: case OPCLASS_CODE_OBJ: case OPCLASS_CONST_OBJ: if ((pterm = FindOpTerm(dwOpcode)) == NULL) { DBG_ERROR(("UnAsmOpcode: invalid opcode 0x%x", dwOpcode)); rc = UNASMERR_FATAL; } else { (*ppbOp)++; rc = UnAsmTermObj(pterm, ppbOp); } break;
default: DBG_ERROR(("UnAsmOpcode: invalid opcode class %d", bOp)); rc = UNASMERR_FATAL; }
return rc; } //UnAsmOpcode
/***LP UnAsmDataObj - Unassemble data object
* * ENTRY * ppbOp -> opcode pointer * * EXIT-SUCCESS * returns UNASMERR_NONE * EXIT-FAILURE * returns negative error code */
LONG LOCAL UnAsmDataObj(PUCHAR *ppbOp) { LONG rc = UNASMERR_NONE; UCHAR bOp = **ppbOp; PSZ psz;
(*ppbOp)++; switch (bOp) { case OP_BYTE: PRINTF("0x%x", **ppbOp); *ppbOp += sizeof(UCHAR); break;
case OP_WORD: PRINTF("0x%x", *((PUSHORT)*ppbOp)); *ppbOp += sizeof(USHORT); break;
case OP_DWORD: PRINTF("0x%x", *((PULONG)*ppbOp)); *ppbOp += sizeof(ULONG); break;
case OP_STRING: PRINTF("\""); for (psz = (PSZ)*ppbOp; *psz != '\0'; psz++) { if (*psz == '\\') { PRINTF("\\"); } PRINTF("%c", *psz); } PRINTF("\""); *ppbOp += STRLEN((PSZ)*ppbOp) + 1; break;
default: DBG_ERROR(("UnAsmDataObj: unexpected opcode 0x%x", bOp)); rc = UNASMERR_INVALID_OPCODE; }
return rc; } //UnAsmDataObj
/***LP UnAsmNameObj - Unassemble name object
* * ENTRY * ppbOp -> opcode pointer * pns -> to hold object found or created * c - object type * * EXIT-SUCCESS * returns UNASMERR_NONE * EXIT-FAILURE * returns negative error code */
LONG LOCAL UnAsmNameObj(PUCHAR *ppbOp, PNSOBJ pns, char c) { LONG rc = UNASMERR_NONE; char szName[MAX_NAME_LEN + 1]; int iLen = 0;
szName[0] = '\0'; if (**ppbOp == OP_ROOT_PREFIX) { szName[iLen] = '\\'; iLen++; (*ppbOp)++; rc = UnAsmNameTail(ppbOp, szName, iLen); } else if (**ppbOp == OP_PARENT_PREFIX) { szName[iLen] = '^'; iLen++; (*ppbOp)++; while ((**ppbOp == OP_PARENT_PREFIX) && (iLen < MAX_NAME_LEN)) { szName[iLen] = '^'; iLen++; (*ppbOp)++; }
if (**ppbOp == OP_PARENT_PREFIX) { DBG_ERROR(("UnAsmNameObj: name too long - \"%s\"", szName)); rc = UNASMERR_FATAL; } else { rc = UnAsmNameTail(ppbOp, szName, iLen); } } else { rc = UnAsmNameTail(ppbOp, szName, iLen); }
if (rc == UNASMERR_NONE) { ULONG_PTR uipns = 0; NSOBJ NSObj;
PRINTF("%s", szName);
rc = GetNSObj(szName, gpnsCurUnAsmScope, &uipns, &NSObj, 0);
if (rc == UNASMERR_NONE) { if (pns != NULL) { MEMCPY(pns, &NSObj, sizeof(NSObj)); }
if ((c == NSTYPE_SCOPE) && (uipns != 0)) { gpnsCurUnAsmScope = pns; } } else { rc = UNASMERR_NONE; } }
return rc; } //UnAsmNameObj
/***LP UnAsmNameTail - Parse AML name tail
* * ENTRY * ppbOp -> opcode pointer * pszBuff -> to hold parsed name * iLen - index to tail of pszBuff * * EXIT-SUCCESS * returns UNASMERR_NONE * EXIT-FAILURE * returns negative error code */
LONG LOCAL UnAsmNameTail(PUCHAR *ppbOp, PSZ pszBuff, int iLen) { LONG rc = UNASMERR_NONE; int icNameSegs = 0;
//
// We do not check for invalid NameSeg characters here and assume that
// the compiler does its job not generating it.
//
if (**ppbOp == '\0') { //
// There is no NameTail (i.e. either NULL name or name with just
// prefixes.
//
(*ppbOp)++; } else if (**ppbOp == OP_MULTI_NAME_PREFIX) { (*ppbOp)++; icNameSegs = (int)**ppbOp; (*ppbOp)++; } else if (**ppbOp == OP_DUAL_NAME_PREFIX) { (*ppbOp)++; icNameSegs = 2; } else icNameSegs = 1;
while ((icNameSegs > 0) && (iLen + sizeof(NAMESEG) < MAX_NAME_LEN)) { STRCPYN(&pszBuff[iLen], (PSZ)(*ppbOp), sizeof(NAMESEG)); iLen += sizeof(NAMESEG); *ppbOp += sizeof(NAMESEG); icNameSegs--; if ((icNameSegs > 0) && (iLen + 1 < MAX_NAME_LEN)) { pszBuff[iLen] = '.'; iLen++; } }
if (icNameSegs > 0) { DBG_ERROR(("UnAsmNameTail: name too long - %s", pszBuff)); rc = UNASMERR_FATAL; } else { pszBuff[iLen] = '\0'; }
return rc; } //UnAsmNameTail
/***LP UnAsmTermObj - Unassemble term object
* * ENTRY * pterm -> term table entry * ppbOp -> opcode pointer * * EXIT-SUCCESS * returns UNASMERR_NONE * EXIT-FAILURE * returns negative error code */
LONG LOCAL UnAsmTermObj(PASLTERM pterm, PUCHAR *ppbOp) { LONG rc = UNASMERR_NONE; PUCHAR pbEnd = NULL; PNSOBJ pnsScopeSave = gpnsCurUnAsmScope; NSOBJ NSObj = {0};
PRINTF("%s", pterm->pszID);
if (pterm->dwfTerm & TF_PACKAGE_LEN) { ParsePackageLen(ppbOp, &pbEnd); }
if (pterm->pszUnAsmArgTypes != NULL) { rc = UnAsmArgs(pterm->pszUnAsmArgTypes, pterm->pszArgActions, ppbOp, &NSObj); }
if (rc == UNASMERR_NONE) { if (pterm->dwfTerm & TF_DATA_LIST) { rc = UnAsmDataList(ppbOp, pbEnd); } else if (pterm->dwfTerm & TF_PACKAGE_LIST) { rc = UnAsmPkgList(ppbOp, pbEnd); } else if (pterm->dwfTerm & TF_FIELD_LIST) { rc = UnAsmFieldList(ppbOp, pbEnd); } else if (pterm->dwfTerm & TF_PACKAGE_LEN) { if ((pterm->dwfTerm & TF_CHANGE_CHILDSCOPE) && (NSObj.ObjData.dwDataType != 0)) { gpnsCurUnAsmScope = &NSObj; }
rc = UnAsmScope(ppbOp, pbEnd, 0, NULL, -1, -1); } } gpnsCurUnAsmScope = pnsScopeSave;
return rc; } //UnAsmTermObj
/***LP UnAsmArgs - Unassemble arguments
* * ENTRY * pszUnArgTypes -> UnAsm ArgTypes string * pszArgActions -> Arg Action types * ppbOp -> opcode pointer * pns -> to hold created object * * EXIT-SUCCESS * returns UNASMERR_NONE * EXIT-FAILURE * returns negative error code */
LONG LOCAL UnAsmArgs(PSZ pszUnAsmArgTypes, PSZ pszArgActions, PUCHAR *ppbOp, PNSOBJ pns) { LONG rc = UNASMERR_NONE; static UCHAR bArgData = 0; int iNumArgs, i; PASLTERM pterm;
iNumArgs = STRLEN(pszUnAsmArgTypes); PRINTF("(");
for (i = 0; i < iNumArgs; ++i) { if (i != 0) { PRINTF(", "); }
switch (pszUnAsmArgTypes[i]) { case 'N': ASSERT(pszArgActions != NULL); rc = UnAsmNameObj(ppbOp, pns, pszArgActions[i]); break;
case 'O': if ((**ppbOp == OP_BUFFER) || (**ppbOp == OP_PACKAGE) || (OpClassTable[**ppbOp] == OPCLASS_CONST_OBJ)) { pterm = FindOpTerm((ULONG)(**ppbOp)); ASSERT(pterm != NULL); (*ppbOp)++; rc = UnAsmTermObj(pterm, ppbOp); } else { rc = UnAsmDataObj(ppbOp); } break;
case 'C': rc = UnAsmOpcode(ppbOp); break;
case 'B': PRINTF("0x%x", **ppbOp); *ppbOp += sizeof(UCHAR); break;
case 'K': case 'k': if (pszUnAsmArgTypes[i] == 'K') { bArgData = **ppbOp; }
if ((pszArgActions != NULL) && (pszArgActions[i] == '!')) { PRINTF("0x%x", **ppbOp & 0x07); } else { pterm = FindKeywordTerm(pszArgActions[i], bArgData); ASSERT(pterm != NULL); PRINTF("%s", pterm->pszID); }
if (pszUnAsmArgTypes[i] == 'K') { *ppbOp += sizeof(UCHAR); } break;
case 'W': PRINTF("0x%x", *((PUSHORT)*ppbOp)); *ppbOp += sizeof(USHORT); break;
case 'D': PRINTF("0x%x", *((PULONG)*ppbOp)); *ppbOp += sizeof(ULONG); break;
case 'S': ASSERT(pszArgActions != NULL); rc = UnAsmSuperName(ppbOp); break;
default: DBG_ERROR(("UnAsmOpcode: invalid ArgType '%c'", pszUnAsmArgTypes[i])); rc = UNASMERR_FATAL; } }
PRINTF(")");
return rc; } //UnAsmArgs
/***LP UnAsmSuperName - Unassemble supername
* * ENTRY * ppbOp -> opcode pointer * * EXIT-SUCCESS * returns UNASMERR_NONE * EXIT-FAILURE * returns negative error code */
LONG LOCAL UnAsmSuperName(PUCHAR *ppbOp) { LONG rc = UNASMERR_NONE;
if (**ppbOp == 0) { (*ppbOp)++; } else if ((**ppbOp == OP_EXT_PREFIX) && (*(*ppbOp + 1) == EXOP_DEBUG)) { PRINTF("Debug"); *ppbOp += 2; } else if (OpClassTable[**ppbOp] == OPCLASS_NAME_OBJ) { rc = UnAsmNameObj(ppbOp, NULL, NSTYPE_UNKNOWN); } else if ((**ppbOp == OP_INDEX) || (OpClassTable[**ppbOp] == OPCLASS_ARG_OBJ) || (OpClassTable[**ppbOp] == OPCLASS_LOCAL_OBJ)) { rc = UnAsmOpcode(ppbOp); } else { DBG_ERROR(("UnAsmSuperName: invalid SuperName - 0x%02x", **ppbOp)); rc = UNASMERR_FATAL; }
return rc; } //UnAsmSuperName
/***LP UnAsmDataList - Unassemble data list
* * ENTRY * ppbOp -> opcode pointer * pbEnd -> end of list * * EXIT-SUCCESS * returns UNASMERR_NONE * EXIT-FAILURE * returns negative error code */
LONG LOCAL UnAsmDataList(PUCHAR *ppbOp, PUCHAR pbEnd) { LONG rc = UNASMERR_NONE; int i;
Indent(*ppbOp, giLevel); PRINTF("{");
while (*ppbOp < pbEnd) { Indent(*ppbOp, 0); PRINTF("0x%02x", **ppbOp);
(*ppbOp)++; for (i = 1; (*ppbOp < pbEnd) && (i < 8); ++i) { PRINTF(", 0x%02x", **ppbOp); (*ppbOp)++; }
if (*ppbOp < pbEnd) { PRINTF(","); } }
Indent(*ppbOp, giLevel); PRINTF("}");
return rc; } //UnAsmDataList
/***LP UnAsmPkgList - Unassemble package list
* * ENTRY * ppbOp -> opcode pointer * pbEnd -> end of list * * EXIT-SUCCESS * returns UNASMERR_NONE * EXIT-FAILURE * returns negative error code */
LONG LOCAL UnAsmPkgList(PUCHAR *ppbOp, PUCHAR pbEnd) { LONG rc = UNASMERR_NONE; PASLTERM pterm;
Indent(*ppbOp, giLevel); PRINTF("{"); giLevel++;
while (*ppbOp < pbEnd) { Indent(*ppbOp, giLevel);
if ((**ppbOp == OP_BUFFER) || (**ppbOp == OP_PACKAGE) || (OpClassTable[**ppbOp] == OPCLASS_CONST_OBJ)) { pterm = FindOpTerm((ULONG)(**ppbOp)); ASSERT(pterm != NULL); (*ppbOp)++; rc = UnAsmTermObj(pterm, ppbOp); } else if (OpClassTable[**ppbOp] == OPCLASS_NAME_OBJ) { rc = UnAsmNameObj(ppbOp, NULL, NSTYPE_UNKNOWN); } else { rc = UnAsmDataObj(ppbOp); }
if (rc != UNASMERR_NONE) { break; } else if (*ppbOp < pbEnd) { PRINTF(","); } }
if (rc == UNASMERR_NONE) { giLevel--; Indent(*ppbOp, giLevel); PRINTF("}"); }
return rc; } //UnAsmPkgList
/***LP UnAsmFieldList - Unassemble field list
* * ENTRY * ppbOp -> opcode pointer * pbEnd -> end of list * * EXIT-SUCCESS * returns UNASMERR_NONE * EXIT-FAILURE * returns negative error code */
LONG LOCAL UnAsmFieldList(PUCHAR *ppbOp, PUCHAR pbEnd) { LONG rc = UNASMERR_NONE; ULONG dwBitPos = 0;
Indent(*ppbOp, giLevel); PRINTF("{"); giLevel++;
while (*ppbOp < pbEnd) { Indent(*ppbOp, giLevel); if ((rc = UnAsmField(ppbOp, &dwBitPos)) == UNASMERR_NONE) { if (*ppbOp < pbEnd) { PRINTF(","); } } else { break; } }
if (rc == UNASMERR_NONE) { giLevel--; Indent(*ppbOp, giLevel); PRINTF("}"); }
return rc; } //UnAsmFieldList
/***LP UnAsmField - Unassemble field
* * ENTRY * ppbOp -> opcode pointer * pdwBitPos -> to hold cumulative bit position * * EXIT-SUCCESS * returns UNASMERR_NONE * EXIT-FAILURE * returns negative error code */
LONG LOCAL UnAsmField(PUCHAR *ppbOp, PULONG pdwBitPos) { LONG rc = UNASMERR_NONE;
if (**ppbOp == 0x01) { PASLTERM pterm = NULL;
(*ppbOp)++; pterm = FindKeywordTerm('A', **ppbOp); if (pterm != NULL) {
PRINTF("AccessAs(%s, 0x%x)", pterm->pszID, *(*ppbOp + 1));
} *ppbOp += 2; } else { char szNameSeg[sizeof(NAMESEG) + 1]; ULONG dwcbBits;
if (**ppbOp == 0) { szNameSeg[0] = '\0'; (*ppbOp)++; } else { STRCPYN(szNameSeg, (PSZ)*ppbOp, sizeof(NAMESEG)); szNameSeg[4] = '\0'; *ppbOp += sizeof(NAMESEG); }
dwcbBits = ParsePackageLen(ppbOp, NULL); if (szNameSeg[0] == '\0') { if ((dwcbBits > 32) && (((*pdwBitPos + dwcbBits) % 8) == 0)) { PRINTF("Offset(0x%x)", (*pdwBitPos + dwcbBits)/8); } else { PRINTF(", %d", dwcbBits); } } else { PRINTF("%s, %d", szNameSeg, dwcbBits); }
*pdwBitPos += dwcbBits; }
return rc; } //UnAsmField
|