diff options
author | Calder Kitagawa <ckitagawa@google.com> | 2018-04-24 13:54:46 +0000 |
---|---|---|
committer | Edward Lesmes <ehmaldonado@google.com> | 2021-07-23 22:09:53 +0000 |
commit | 05b1b6a1d8cfe2960959ff0ea3ecf96c4f198c54 (patch) | |
tree | c73343189a18e17ada847085bd27d0053e49d3ab /image_utils.h | |
parent | 451ff5de400706acdfcfdb9bf28ca6d4c0670b81 (diff) | |
download | zucchini-05b1b6a1d8cfe2960959ff0ea3ecf96c4f198c54.tar.gz |
[Zucchini] Update ExecutableType values.
This change has some pros and some cons:
Pros:
- Human readable ExecType in patch/hex dumps as the ASCII is meaningful.
- Can be done at next to no cost at compile time.
- Assigning new values regardless of order of appearance in the enum is
more flexible. No more concern over invalidating old patches as values
will be more or less permanent once this change goes in.
Cons:
- Checking if an ExecutableType is valid requires O(n) time where n
is the number of supported Exec types using a cast.
Alternatively, we could maintain a sorted list of these types in
memory to check against in O(log(n)) or could use a set
but this is more memory. Overall not a huge deal since we only support
~9 types but it is worth understanding the tradeoffs.
- Enums don't enforce value reuse so it is possible although highly
unlikely we introduce a repeated value. However, given the use of the
switch case casting requiring unique values this is very unlikely.
Bug: 834932
Change-Id: I7bc14ea7b4434e60bb0dafa47178fb2c2c12dc7f
Reviewed-on: https://chromium-review.googlesource.com/1020446
Commit-Queue: Calder Kitagawa <ckitagawa@google.com>
Reviewed-by: Samuel Huang <huangs@chromium.org>
Cr-Commit-Position: refs/heads/master@{#553083}
NOKEYCHECK=True
GitOrigin-RevId: da4335f0d27c7fa14f6897ffeb0833d424860f7e
Diffstat (limited to 'image_utils.h')
-rw-r--r-- | image_utils.h | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/image_utils.h b/image_utils.h index 3765763..868e358 100644 --- a/image_utils.h +++ b/image_utils.h @@ -8,6 +8,7 @@ #include <stddef.h> #include <stdint.h> +#include "base/macros.h" #include "base/numerics/safe_conversions.h" #include "base/optional.h" #include "components/zucchini/buffer_view.h" @@ -137,20 +138,51 @@ struct EquivalenceCandidate { double similarity; }; -// Enumerations for supported executables. +template <size_t N> +inline constexpr uint32_t ExeTypeToUint32(const char (&exe_type)[N]) { + static_assert(N == 5, "Expected ExeType of length 4 + 1 null byte."); + return (exe_type[3] << 24) | (exe_type[2] << 16) | (exe_type[1] << 8) | + exe_type[0]; +} + +// Enumerations for supported executables. Values in this enum must be distinct. +// Once present, values should never be altered or removed to ensure backwards +// compatibility and patch type collision avoidance. enum ExecutableType : uint32_t { kExeTypeUnknown = UINT32_MAX, - kExeTypeNoOp = 0, - kExeTypeWin32X86 = 1, - kExeTypeWin32X64 = 2, - kExeTypeElfX86 = 3, - kExeTypeElfX64 = 4, - kExeTypeElfArm32 = 5, - kExeTypeElfAArch64 = 6, - kExeTypeDex = 7, - kNumExeType + kExeTypeNoOp = ExeTypeToUint32("NoOp"), + kExeTypeWin32X86 = ExeTypeToUint32("Px86"), + kExeTypeWin32X64 = ExeTypeToUint32("Px64"), + kExeTypeElfX86 = ExeTypeToUint32("Ex86"), + kExeTypeElfX64 = ExeTypeToUint32("Ex64"), + kExeTypeElfArm32 = ExeTypeToUint32("EA32"), + kExeTypeElfAArch64 = ExeTypeToUint32("EA64"), + kExeTypeDex = ExeTypeToUint32("DEX "), }; +constexpr ExecutableType CastToExecutableType(uint32_t possible_exe_type) { + switch (static_cast<ExecutableType>(possible_exe_type)) { + case kExeTypeNoOp: // Falls through. + case kExeTypeWin32X86: // Falls through. + case kExeTypeWin32X64: // Falls through. + case kExeTypeElfX86: // Falls through. + case kExeTypeElfX64: // Falls through. + case kExeTypeElfArm32: // Falls through. + case kExeTypeElfAArch64: // Falls through. + case kExeTypeDex: // Falls through. + case kExeTypeUnknown: + return static_cast<ExecutableType>(possible_exe_type); + default: + NOTREACHED() << "Unknown type."; + return kExeTypeUnknown; + } +} + +inline std::string CastExecutableTypeToString(ExecutableType exe_type) { + uint32_t v = static_cast<uint32_t>(exe_type); + return {v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF, (v >> 24) & 0xFF}; +} + // A region in an image with associated executable type |exe_type|. If // |exe_type == kExeTypeNoOp|, then the Element represents a region of raw data. struct Element : public BufferRegion { |