fold/third_party/ghidra-decompiler/cpp/float.hh
trvon 5152d0c9f7
feat(binary): vendor Ghidra 12.1 decompiler + validate P-Code lifting (Phase 0-1)
Foundation for replacing fold's dead/abstract binary encoder with a real
SSA P-Code frontend. Verified root-cause gap: serializeBinaryIR() emits only
data-discovery nodes (sections/strings/imports/exports); the control-flow
BinaryExprKind values (BasicBlock/CallSite/...) are never constructed, so the
Z3-BB encoder's encodable filter is always empty and encodeBinaryBBs never
runs — hence 0 binary Z3 findings. The P-Code pipeline supersedes that path.

Phase 0 — docs/internal/ghidra-pcode-integration-research.md: P-Code opcode
core, the decompiler C++ embedding API (LoadImage/SleighArchitecture/Funcdata),
the CORE+DECCORE+SLEIGH source sets, no-bison finding, and pypcode as build
reference.

Phase 1 — vendored Ghidra decompiler at pinned commit (Ghidra_12.1_build,
7e89d94e34...) under third_party/ghidra-decompiler/ (cpp + AArch64 specs +
Apache-2.0 LICENSE + VENDOR.md + .gitignore for build artifacts). Validated by
hand on this clang-21/macOS toolchain:
  - full SSA engine (CORE+DECCORE+SLEIGH, 80 files incl. heritage/funcdata/
    action) compiles clean, -std=c++11 -O2, NO BFD, NO bison (generated
    parsers are committed upstream; ruleparse isn't in the lib set);
  - sleigh compiler builds; AArch64 .slaspec -> .sla compiles;
  - tools/pcode_dump.cpp (custom LoadImage, no BFD) lifts the real arm64
    sym._div_by_zero_direct to correct P-Code: `mov w9,#0 -> COPY(const 0)`,
    `sdiv -> INT_SDIV(w8,w9)` — divisor zero-ness explicit in the data flow,
    so the Phase-3 encoder proves div-by-zero trivially, multi-arch.

Not yet meson-wired (next step) and no fold-side IR/encoder yet (Phase 2-3);
this commit is the validated vendor + smoke tool.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 17:32:47 -04:00

100 lines
5.2 KiB
C++

/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/// \file float.hh
/// \brief Support for decoding different floating-point formats
#ifndef __FLOAT_HH__
#define __FLOAT_HH__
#include "error.hh"
namespace ghidra {
/// \brief Encoding information for a single floating-point format
///
/// This class supports manipulation of a single floating-point encoding.
/// An encoding can be converted to and from the host format and
/// convenience methods allow p-code floating-point operations to be
/// performed on natively encoded operands. This follows the IEEE754 standards.
class FloatFormat {
public:
/// \brief The various classes of floating-point encodings
enum floatclass {
normalized = 0, ///< A normal floating-point number
infinity = 1, ///< An encoding representing an infinite value
zero = 2, ///< An encoding of the value zero
nan = 3, ///< An invalid encoding, Not-a-Number
denormalized = 4 ///< A denormalized encoding (for very small values)
};
private:
int4 size; ///< Size of float in bytes (this format)
int4 signbit_pos; ///< Bit position of sign bit
int4 frac_pos; ///< (lowest) bit position of fractional part
int4 frac_size; ///< Number of bits in fractional part
int4 exp_pos; ///< (lowest) bit position of exponent
int4 exp_size; ///< Number of bits in exponent
int4 bias; ///< What to add to real exponent to get encoding
int4 maxexponent; ///< Maximum possible exponent
int4 decimalMinPrecision; ///< Minimum decimal digits of precision guaranteed by the format
int4 decimalMaxPrecision; ///< Maximum decimal digits of precision needed to uniquely represent value
bool jbitimplied; ///< Set to \b true if integer bit of 1 is assumed
static double createFloat(bool sign,uintb signif,int4 exp); ///< Create a double given sign, fractional, and exponent
static floatclass extractExpSig(double x,bool *sgn,uintb *signif,int4 *exp);
static bool roundToNearestEven(uintb &signif, int4 lowbitpos);
uintb setFractionalCode(uintb x,uintb code) const; ///< Set the fractional part of an encoded value
uintb setSign(uintb x,bool sign) const; ///< Set the sign bit of an encoded value
uintb setExponentCode(uintb x,uintb code) const; ///< Set the exponent of an encoded value
uintb getZeroEncoding(bool sgn) const; ///< Get an encoded zero value
uintb getInfinityEncoding(bool sgn) const; ///< Get an encoded infinite value
uintb getNaNEncoding(bool sgn) const; ///< Get an encoded NaN value
void calcPrecision(void); ///< Calculate the decimal precision of this format
public:
FloatFormat(int4 sz); ///< Construct default IEEE 754 standard settings
int4 getSize(void) const { return size; } ///< Get the size of the encoding in bytes
double getHostFloat(uintb encoding,floatclass *type) const; ///< Convert an encoding into host's double
uintb getEncoding(double host) const; ///< Convert host's double into \b this encoding
uintb convertEncoding(uintb encoding,const FloatFormat *formin) const; ///< Convert between two different formats
uintb extractFractionalCode(uintb x) const; ///< Extract the fractional part of the encoding
bool extractSign(uintb x) const; ///< Extract the sign bit from the encoding
int4 extractExponentCode(uintb x) const; ///< Extract the exponent from the encoding
string printDecimal(double host,bool forcesci) const; ///< Print given value as a decimal string
// Operations on floating point values
uintb opEqual(uintb a,uintb b) const; ///< Equality comparison (==)
uintb opNotEqual(uintb a,uintb b) const; ///< Inequality comparison (!=)
uintb opLess(uintb a,uintb b) const; ///< Less-than comparison (<)
uintb opLessEqual(uintb a,uintb b) const; ///< Less-than-or-equal comparison (<=)
uintb opNan(uintb a) const; ///< Test if Not-a-Number (NaN)
uintb opAdd(uintb a,uintb b) const; ///< Addition (+)
uintb opDiv(uintb a,uintb b) const; ///< Division (/)
uintb opMult(uintb a,uintb b) const; ///< Multiplication (*)
uintb opSub(uintb a,uintb b) const; ///< Subtraction (-)
uintb opNeg(uintb a) const; ///< Unary negate
uintb opAbs(uintb a) const; ///< Absolute value (abs)
uintb opSqrt(uintb a) const; ///< Square root (sqrt)
uintb opTrunc(uintb a,int4 sizeout) const; ///< Convert floating-point to integer
uintb opCeil(uintb a) const; ///< Ceiling (ceil)
uintb opFloor(uintb a) const; ///< Floor (floor)
uintb opRound(uintb a) const; ///< Round
uintb opInt2Float(uintb a,int4 sizein) const; ///< Convert integer to floating-point
uintb opFloat2Float(uintb a,const FloatFormat &outformat) const; ///< Convert between floating-point precisions
};
} // End namespace ghidra
#endif