🗊 Презентация Decompiler internals: microcode

Нажмите для полного просмотра!
Decompiler internals: microcode, слайд №1 Decompiler internals: microcode, слайд №2 Decompiler internals: microcode, слайд №3 Decompiler internals: microcode, слайд №4 Decompiler internals: microcode, слайд №5 Decompiler internals: microcode, слайд №6 Decompiler internals: microcode, слайд №7 Decompiler internals: microcode, слайд №8 Decompiler internals: microcode, слайд №9 Decompiler internals: microcode, слайд №10 Decompiler internals: microcode, слайд №11 Decompiler internals: microcode, слайд №12 Decompiler internals: microcode, слайд №13 Decompiler internals: microcode, слайд №14 Decompiler internals: microcode, слайд №15 Decompiler internals: microcode, слайд №16 Decompiler internals: microcode, слайд №17 Decompiler internals: microcode, слайд №18 Decompiler internals: microcode, слайд №19 Decompiler internals: microcode, слайд №20 Decompiler internals: microcode, слайд №21 Decompiler internals: microcode, слайд №22 Decompiler internals: microcode, слайд №23 Decompiler internals: microcode, слайд №24 Decompiler internals: microcode, слайд №25 Decompiler internals: microcode, слайд №26 Decompiler internals: microcode, слайд №27 Decompiler internals: microcode, слайд №28 Decompiler internals: microcode, слайд №29 Decompiler internals: microcode, слайд №30 Decompiler internals: microcode, слайд №31 Decompiler internals: microcode, слайд №32 Decompiler internals: microcode, слайд №33 Decompiler internals: microcode, слайд №34 Decompiler internals: microcode, слайд №35 Decompiler internals: microcode, слайд №36 Decompiler internals: microcode, слайд №37 Decompiler internals: microcode, слайд №38 Decompiler internals: microcode, слайд №39 Decompiler internals: microcode, слайд №40 Decompiler internals: microcode, слайд №41 Decompiler internals: microcode, слайд №42 Decompiler internals: microcode, слайд №43 Decompiler internals: microcode, слайд №44 Decompiler internals: microcode, слайд №45 Decompiler internals: microcode, слайд №46 Decompiler internals: microcode, слайд №47 Decompiler internals: microcode, слайд №48 Decompiler internals: microcode, слайд №49 Decompiler internals: microcode, слайд №50 Decompiler internals: microcode, слайд №51 Decompiler internals: microcode, слайд №52 Decompiler internals: microcode, слайд №53 Decompiler internals: microcode, слайд №54 Decompiler internals: microcode, слайд №55 Decompiler internals: microcode, слайд №56 Decompiler internals: microcode, слайд №57 Decompiler internals: microcode, слайд №58

Содержание

Вы можете ознакомиться и скачать презентацию на тему Decompiler internals: microcode. Доклад-сообщение содержит 58 слайдов. Презентации для любого класса можно скачать бесплатно. Если материал и наш сайт презентаций Mypresentation Вам понравились – поделитесь им с друзьями с помощью социальных кнопок и добавьте в закладки в своем браузере.

Слайды и текст этой презентации


Слайд 1


Decompiler internals: microcode
Описание слайда:
Decompiler internals: microcode

Слайд 2


Presentation Outline Decompiler architecture Overview of the microcode Opcodes and operands Stack and registers Data flow analysis, aliasibility...
Описание слайда:
Presentation Outline Decompiler architecture Overview of the microcode Opcodes and operands Stack and registers Data flow analysis, aliasibility Microcode availability Your feedback Online copy of this presentation is available at

Слайд 3


Hex-Rays Decompiler Interactive, fast, robust, and programmable decompiler Can handle x86, x64, ARM, ARM64, PowerPC Runs on top of IDA Pro Has been...
Описание слайда:
Hex-Rays Decompiler Interactive, fast, robust, and programmable decompiler Can handle x86, x64, ARM, ARM64, PowerPC Runs on top of IDA Pro Has been evolving for more than 10 years Internals were not really published Namely, the intermediate language

Слайд 4


Decompiler architecture It uses very straightforward sequence of steps:
Описание слайда:
Decompiler architecture It uses very straightforward sequence of steps:

Слайд 5


Decompiler architecture We will focus on the first two steps:
Описание слайда:
Decompiler architecture We will focus on the first two steps:

Слайд 6


Why microcode? It helps to get rid of the complexity of processor instructions Also we get rid of processor idiosyncrasies. Examples: x86: segment...
Описание слайда:
Why microcode? It helps to get rid of the complexity of processor instructions Also we get rid of processor idiosyncrasies. Examples: x86: segment registers, fpu stack ARM: thumb mode addresses PowerPC: multiple copies of CF register (and other condition registers) MIPS: delay slots Sparc: stack windows It makes the decompiler portable. We “just” need to replace the microcode generator Writing a decompiler without an intermediate language looks like waste of time

Слайд 7


Is implementing an IR difficult? Your call :) How many IR languages to you know?
Описание слайда:
Is implementing an IR difficult? Your call :) How many IR languages to you know?

Слайд 8


Why not use an existing IR? There are tons of other intermediate languages: LLVM, REIL, Binary Ninja's ILs, RetDec's IL, etc. Yes, we could use...
Описание слайда:
Why not use an existing IR? There are tons of other intermediate languages: LLVM, REIL, Binary Ninja's ILs, RetDec's IL, etc. Yes, we could use something But I started to work on the microcode when none of the above languages existed This is the main reason why we use our own IR

Слайд 9


A long evolution I started to work on the microcode in 1998 or earlier The name is nothing fancy but reflects the nature of it Some design decisions...
Описание слайда:
A long evolution I started to work on the microcode in 1998 or earlier The name is nothing fancy but reflects the nature of it Some design decisions turned out to be bad (and some of them are already very difficult to fix) For example, the notion of virtual stack registers We will fix it, though. Just takes time Even today we modify our microcode when necessary For example, I reshuffled the instruction opcodes for this talk...

Слайд 10


Design highlights Simplicity: No processor specific stuff One microinstruction does one thing Small number of instructions (only 45 in 1999, now 72)...
Описание слайда:
Design highlights Simplicity: No processor specific stuff One microinstruction does one thing Small number of instructions (only 45 in 1999, now 72) Simple instruction operands (register, number, memory) Consider only compiler generated code Discard things we do not care about: Instruction timing (anyway it is a lost battle) Instruction order (exceptions are a problem!) Order of memory accesses (later we added logic to preserve indirect memory accesses) Handcrafted code

Слайд 11


Generated microcode Initially the microcode looks like RISC code: Memory loads and stores are done using dedicated microinstructions The desired...
Описание слайда:
Generated microcode Initially the microcode looks like RISC code: Memory loads and stores are done using dedicated microinstructions The desired operation is performed on registers Microinstructions have no side effects Each output register is initialized by a separate microinstruction It is very verbose. Example:

Слайд 12


Initial microcode: very verbose
Описание слайда:
Initial microcode: very verbose

Слайд 13


The first optimization pass Only 8 microinstructions Some intermediate registers disappeared Sub-instructions appeared Still too noisy and verbose
Описание слайда:
The first optimization pass Only 8 microinstructions Some intermediate registers disappeared Sub-instructions appeared Still too noisy and verbose

Слайд 14


Further microcode transformations And the final code is: This code is ready to be translated to ctree. (numbers in curly braces are value numbers)...
Описание слайда:
Further microcode transformations And the final code is: This code is ready to be translated to ctree. (numbers in curly braces are value numbers) The output will look like this:

Слайд 15


Minor details Reading microcode is not easy (but hey, it was not designed for that! :) All operand sizes are spelled out explicitly The initial...
Описание слайда:
Minor details Reading microcode is not easy (but hey, it was not designed for that! :) All operand sizes are spelled out explicitly The initial microcode is very simple (RISC like) As we transform microcode, nested subinstructions may appear We implemented the translation from processor instructions to microinstructions in plain C++ We do not use automatic code generators or machine descriptions to generate them. Anyway there are too many processor specific details to make them feasible

Слайд 16


Opcodes: constants and move Copy from (l) to (d)estination Operand sizes must match
Описание слайда:
Opcodes: constants and move Copy from (l) to (d)estination Operand sizes must match

Слайд 17


Opcodes: changing operand size Copy from (l) to (d)estination Operand sizes must differ Since real world programs work with partial registers (like...
Описание слайда:
Opcodes: changing operand size Copy from (l) to (d)estination Operand sizes must differ Since real world programs work with partial registers (like al, ah), we absolutely need low/high

Слайд 18


Opcodes: load and store {sel, off} is a segment:offset pair Usually seg is ds or cs; for processors with flat memory it is ignored 'off' is the most...
Описание слайда:
Opcodes: load and store {sel, off} is a segment:offset pair Usually seg is ds or cs; for processors with flat memory it is ignored 'off' is the most interesting part, it is a memory address

Слайд 19


Opcodes: comparisons Compare (l)left against (r)right The result is stored into (d)estination, a bit register like CF,ZF,SF,...
Описание слайда:
Opcodes: comparisons Compare (l)left against (r)right The result is stored into (d)estination, a bit register like CF,ZF,SF,...

Слайд 20


Opcodes: arithmetic and bitwise operations Operand sizes must be the same The result is stored into (d)estination
Описание слайда:
Opcodes: arithmetic and bitwise operations Operand sizes must be the same The result is stored into (d)estination

Слайд 21


Opcodes: shifts (and rotations?) Shift (l)eft by the amount specified in (r)ight The result is stored into (d)estination Initially our microcode had...
Описание слайда:
Opcodes: shifts (and rotations?) Shift (l)eft by the amount specified in (r)ight The result is stored into (d)estination Initially our microcode had rotation operations but they turned out to be useless because they can not be nicely represented in C

Слайд 22


Opcodes: condition codes Perform the operation on (l)left and (r)ight Generate carry or overflow bits Store CF or OF into (d)estination We need these...
Описание слайда:
Opcodes: condition codes Perform the operation on (l)left and (r)ight Generate carry or overflow bits Store CF or OF into (d)estination We need these instructions to precisely track carry and overflow bits Normally these instructions get eliminated during microcode transformations

Слайд 23


Opcodes: unconditional flow control Initially calls have only the callee address The decompiler retrieves the callee prototype from the database or...
Описание слайда:
Opcodes: unconditional flow control Initially calls have only the callee address The decompiler retrieves the callee prototype from the database or tries to guess it After that the 'd' operand contains all information about the call, including the function prototype and actual arguments

Слайд 24


Opcodes: conditional jumps Compare (l)eft against (r)right and jump to (d)estination if the condition holds Jtbl is used to represent 'switch' idioms
Описание слайда:
Opcodes: conditional jumps Compare (l)eft against (r)right and jump to (d)estination if the condition holds Jtbl is used to represent 'switch' idioms

Слайд 25


Opcodes: floating point operations Basically we have conversions and a few arithmetic operations There is little we can do with these operations,...
Описание слайда:
Opcodes: floating point operations Basically we have conversions and a few arithmetic operations There is little we can do with these operations, they are not really optimizable Other fp operations use helper functions (e.g. sqrt)

Слайд 26


Opcodes: miscellaneous Some operations can not be expressed in microcode If possible, we use intrinsic calls for them (e.g. sqrtpd) If no intrinsic...
Описание слайда:
Opcodes: miscellaneous Some operations can not be expressed in microcode If possible, we use intrinsic calls for them (e.g. sqrtpd) If no intrinsic call exists, we use “ext” for them and only try to keep track of data dependencies (e.g. “aam”) “und” is used when a register is spoiled in a way that we can not predict or describe (e.g. ZF after mul)

Слайд 27


More opcodes? We quickly reviewed all 72 instructions Probably we should extend microcode Ternary operator? Post-increment and post-decrement? All...
Описание слайда:
More opcodes? We quickly reviewed all 72 instructions Probably we should extend microcode Ternary operator? Post-increment and post-decrement? All this requires more research

Слайд 28


Operands! As everyone else, initially we had only: constant integer numbers registers Life was simple and easy in the good old days! Alas, the...
Описание слайда:
Operands! As everyone else, initially we had only: constant integer numbers registers Life was simple and easy in the good old days! Alas, the reality is more diverse. We quickly added: stack variables global variables address of an operand list of cases (for switches) result of another instruction helper functions call arguments string and floating point constants

Слайд 29


Register operands The microcode engine provides unlimited (in theory) number of microregisters Processor registers are mapped to microregisters: eax...
Описание слайда:
Register operands The microcode engine provides unlimited (in theory) number of microregisters Processor registers are mapped to microregisters: eax => microregisters (mreg) 8, 9, 10, 11 al => mreg 8 ah => mreg 9 Usually there are more microregisters than the processor registers. We allocate them as needed when generating microcode Examples:

Слайд 30


Stack as microregisters I was reluctant to introduce a new operand type for stack variables and decided to map the stack frame to microregisters...
Описание слайда:
Stack as microregisters I was reluctant to introduce a new operand type for stack variables and decided to map the stack frame to microregisters Like, the stack frame is mapped to the microregister #100 and higher A bright idea? Nope! Very soon I realized that we have to handle indirect references to the stack frame Not really possible with microregisters But there was so much code relying on this concept that we still have it Laziness pays off now and in the future (negatively)

Слайд 31


Stack as viewed by the decompiler Yellow part is mapped to microregisters Red is aliasable
Описание слайда:
Stack as viewed by the decompiler Yellow part is mapped to microregisters Red is aliasable

Слайд 32


More operand types! 64-bit values are represented as pairs of registers Usually it is a standard pair like edx:eax Compilers get better and nowadays...
Описание слайда:
More operand types! 64-bit values are represented as pairs of registers Usually it is a standard pair like edx:eax Compilers get better and nowadays use any registers as a pair; or even pair a stack location with a register: sp+4:esi We ended up with a new operand type: operand pair It consists of low and high halves They can be located anywhere (stack, registers, glbmem)

Слайд 33


Scattered operands The nightmare has just begun, in fact Modern compilers use very intricate rules to pass structs and unions by value to and from...
Описание слайда:
Scattered operands The nightmare has just begun, in fact Modern compilers use very intricate rules to pass structs and unions by value to and from the called functions A register like RDI may contain multiple structure fields Some structure fields may be passed on the stack Some in the floating registers Some in general registers (unaligned wrt register start) We had no other choice but to add scattered operands that can represent all the above

Слайд 34


A simple scattered return value A function that returns a struct in rax: Assembler code:
Описание слайда:
A simple scattered return value A function that returns a struct in rax: Assembler code:

Слайд 35


A simple scattered return value …and the output is: Our decompiler managed to represent things nicely! Similar or more complex situations exist for...
Описание слайда:
A simple scattered return value …and the output is: Our decompiler managed to represent things nicely! Similar or more complex situations exist for all 64-bit processors Support for scattered operands is not complete yet but we constantly improve it

Слайд 36


More detailed look at microcode transformations The initial “preoptimization” step uses very simple constant and register propagation algorithm It is...
Описание слайда:
More detailed look at microcode transformations The initial “preoptimization” step uses very simple constant and register propagation algorithm It is very fast It gets rid of most temporary registers and reduces the microcode size by two Normally we use a more sophisticated propagation algorithm It also works on the basic block level It is much slower but can: handle partial registers (propagate eax into an expression that uses ah) move entire instruction inside another work with operands other that registers (stack and global memory, pair and scattered operands)

Слайд 37


Global optimization We build the control flow graph Perform data flow analysis to find where each operand is used or defined The use/def information...
Описание слайда:
Global optimization We build the control flow graph Perform data flow analysis to find where each operand is used or defined The use/def information is used to: delete dead code (if the instruction result is not used, then we delete the instruction) propagate operands and instructions across block boundaries generate assertions for future optimizations (we know that eax is zero at the target of “jz eax” if there are no other predecessors; so we generate “mov 0, eax”)

Слайд 38


Synthetic assertion instructions If jump is not taken, then we know that eax is zero Assertions can be propagated and lead to more simplifications
Описание слайда:
Synthetic assertion instructions If jump is not taken, then we know that eax is zero Assertions can be propagated and lead to more simplifications

Слайд 39


Simple algebraic transformations We have implemented (in plain C++) hundreds of very small optimization rules. For example: They are simple and sound...
Описание слайда:
Simple algebraic transformations We have implemented (in plain C++) hundreds of very small optimization rules. For example: They are simple and sound They apply to all cases without exceptions Overall the decompiler uses sound rules They do not depend on the compiler

Слайд 40


More complex rules For example, this rule recognizes 64-bit subtractions: We have a swarm of rules like this. They work like little ants :)
Описание слайда:
More complex rules For example, this rule recognizes 64-bit subtractions: We have a swarm of rules like this. They work like little ants :)

Слайд 41


Data dependency dependent rules Naturally, all these rules are compiler-independent, they use common algebraic number properties Unfortunately we do...
Описание слайда:
Data dependency dependent rules Naturally, all these rules are compiler-independent, they use common algebraic number properties Unfortunately we do not have a language to describe these rules, so we manually added these rules in C++ However, the pattern recognition does not naively check if the previous or next instruction is the expected one. We use data dependencies to find the instructions that form the pattern For example, the rule CMB43 looks for the 'low' instruction by searching forward for an instruction that accesses the 'x' operand:

Слайд 42


Interblock rules Some rules work across multiple blocks:
Описание слайда:
Interblock rules Some rules work across multiple blocks:

Слайд 43


Interblock rules: signed division by power2 Signed division is sometimes replaced by a shift: A simple rule transforms it back:
Описание слайда:
Interblock rules: signed division by power2 Signed division is sometimes replaced by a shift: A simple rule transforms it back:

Слайд 44


Hooks It is possible to hook to the optimization engine and add your own transformation rules The Decompiler SDK has some examples how to do it...
Описание слайда:
Hooks It is possible to hook to the optimization engine and add your own transformation rules The Decompiler SDK has some examples how to do it Currently it is not possible to disable an existing rule However, since (almost?) all of them are sound and do not use heuristics, it is not a problem In fact the processor specific parts of the decompiler internally use these hooks as well

Слайд 45


ARM hooks For example, the ARM decompiler has the following rule: so that a construct like this: BX LR will be converted into: RET only if we can...
Описание слайда:
ARM hooks For example, the ARM decompiler has the following rule: so that a construct like this: BX LR will be converted into: RET only if we can prove that the value of LR at the "BX LR" instruction is equal to the initial value of LR at the entry point. However, how do we find if we jump to the initial_lr? Data analysis is to help us

Слайд 46


Data flow analysis In fact virtually all transformation rules are based on data flow analysis. Very rarely we check the previous or the next...
Описание слайда:
Data flow analysis In fact virtually all transformation rules are based on data flow analysis. Very rarely we check the previous or the next instruction for pattern matching Instead, we calculate the use/def lists for the instruction and search for the instructions that access them We keep track of what is used and what is defined by every microinstruction (in red). These lists are calculated when necessary:

Слайд 47


Use-def lists Similar lists are maintained for each block. Instead of calculating them on request we keep them precalculated: We keep both “must” and...
Описание слайда:
Use-def lists Similar lists are maintained for each block. Instead of calculating them on request we keep them precalculated: We keep both “must” and “may” access lists The values in parenthesis are part of the “may” list For example, an indirect memory access may read any memory:

Слайд 48


Usefulness of use-def lists Based on use-def lists of each block the decompiler can build global use-def chains and answer questions like: Is a...
Описание слайда:
Usefulness of use-def lists Based on use-def lists of each block the decompiler can build global use-def chains and answer questions like: Is a defined value used anywhere? If yes, where exactly? Just one location? If yes, what about moving the definition there? If the value is used nowhere, what about deleting it? Where does a value come from? If only from one location, can we propagate (or even move) it? What are the values are the used but never defined?These are the candidates for input arguments What are the values that are defined but never used but reach the last block? These are the candidates for the return values

Слайд 49


Global propagation in action Image we have code like this:
Описание слайда:
Global propagation in action Image we have code like this:

Слайд 50


Global propagation in action The use-def chains clearly show that esi is defined only in block #1: Therefore it can be propagated:
Описание слайда:
Global propagation in action The use-def chains clearly show that esi is defined only in block #1: Therefore it can be propagated:

Слайд 51


Data flow analysis The devil is in details Our analysis engine can handle partial registers (they are a pain) Big endian and little endian can be...
Описание слайда:
Data flow analysis The devil is in details Our analysis engine can handle partial registers (they are a pain) Big endian and little endian can be handled as well (however, we sometimes end up with the situations when a part of the operand is little endian and another part – big endian) The stack frame and registers are handled Registers can be addressed only directly Stack location can be addressed indirectly and our analysis takes this into account Well, we have to make some assumptions...

Слайд 52


Aliasability Take this example: can we claim that %stkvar == 1 after stx? Naturally, in general case we can not But it turns out that in some case we...
Описание слайда:
Aliasability Take this example: can we claim that %stkvar == 1 after stx? Naturally, in general case we can not But it turns out that in some case we can claim it Namely: If we haven't taken the address of any stack variable Or, if we did, the address we took is higher (*) Or, if the address is lower, it was not moved into eax Overall it is a tough question

Слайд 53


Stack as viewed by the decompiler Yellow part is mapped to microregisters Red is aliasable
Описание слайда:
Stack as viewed by the decompiler Yellow part is mapped to microregisters Red is aliasable

Слайд 54


Minimal stack reference Aliasability is unsolvable problem in general We should optimize things only if we can prove the correctness of the...
Описание слайда:
Minimal stack reference Aliasability is unsolvable problem in general We should optimize things only if we can prove the correctness of the transformation We keep track of expressions like &stkvar and calculate the minimal reference (minstkref) We assume that everything below minstkref can be accessed only directly, i.e. is not aliasable We propagate this information over the control graph One value is maintained per block (we could probably improve things by calculating minstkref for each instruction) A similar value is maintained for the incoming stack arguments (minargref)

Слайд 55


Minstkref propagation We use the control flow graph:
Описание слайда:
Minstkref propagation We use the control flow graph:

Слайд 56


Testing the microcode Microcode if verified for consistency after every transformation BTW, third party plugins should do the same Very few microcode...
Описание слайда:
Testing the microcode Microcode if verified for consistency after every transformation BTW, third party plugins should do the same Very few microcode related bug reports We have quite extensive test suites that constantly grow A hundred or so of processors cores running tests However, after publishing microcode there will be a new wave of bug reports Found a bug? Send us the database with the description how to reproduce it Most problems are solved within one day or faster

Слайд 57


Publishing microcode The microcode API for C++ will be available in the next version of IDA Python API won't be available yet We will start beta...
Описание слайда:
Publishing microcode The microcode API for C++ will be available in the next version of IDA Python API won't be available yet We will start beta testing the next week Decompiler users with active support: feel free to send an email to support@hex-rays.com if you want to participate Check out the sample plugins that show how to use the new API

Слайд 58


Was it interesting? Thank you for your attention! Questions?
Описание слайда:
Was it interesting? Thank you for your attention! Questions?



Похожие презентации
Mypresentation.ru
Загрузить презентацию