Skip to content

Commit

Permalink
-Upgrade to C++17.
Browse files Browse the repository at this point in the history
-Use optional for byte offset of fields.
-When  byte offset value is empty, write NULL to db. This allows to make a distinction between unions and structs.
-TODO:Finish union unit testing.
-TODO:Add union support documentation.
  • Loading branch information
lorenzo-gomez-windhover committed Oct 11, 2024
1 parent 112854f commit bdd9546
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 90 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ UT_OBJ_32 := $(UT_OBJ_32:$(UT_SRC_DIR)/test_file%.cpp=$(UT_OBJ_32BIT_DIR)/te


# Set target flags
CPPFLAGS := -MMD -MP -std=c++14 -fmessage-length=0 $(INCLUDES)
CPPFLAGS := -MMD -MP -std=c++17 -fmessage-length=0 $(INCLUDES)
CFLAGS := -Wall -g3
CFLAGS_32BIT := -Wall -g3 -m32
LDFLAGS := -Llib
Expand Down
15 changes: 8 additions & 7 deletions src/Field.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
Field::Field(Symbol& inSymbol, Symbol& inType)
: symbol{inSymbol}, // @suppress("Symbol is not resolved")
name{""},
byte_offset{0},
byte_offset{std::nullopt},
type{inType}, // @suppress("Symbol is not resolved")
dimensionList{},
little_endian{false},
Expand All @@ -22,7 +22,7 @@ Field::Field(Symbol& inSymbol, Symbol& inType)
type.getName().c_str(), dimensionList.toString(), little_endian ? "LE" : "BE");
}

Field::Field(Symbol& inSymbol, std::string& inName, uint32_t inByteOffset, Symbol& inType, DimensionList& inDimensionList, bool inLittleEndian,
Field::Field(Symbol& inSymbol, std::string& inName, std::optional<uint32_t> inByteOffset, Symbol& inType, DimensionList& inDimensionList, bool inLittleEndian,
uint32_t inBitSize, uint32_t inBitOffset)
: symbol{inSymbol}, // @suppress("Symbol is not resolved")
name{inName}, // @suppress("Symbol is not resolved")
Expand All @@ -41,7 +41,8 @@ Field::Field(Symbol& inSymbol, std::string& inName, uint32_t inByteOffset, Symbo
type.getName().c_str(), dimensionList.toString(), little_endian ? "LE" : "BE");
}

Field::Field(Symbol& inSymbol, std::string& inName, uint32_t inByteOffset, Symbol& inType, bool inLittleEndian, uint32_t inBitSize, uint32_t inBitOffset)
Field::Field(Symbol& inSymbol, std::string& inName, std::optional<uint32_t> inByteOffset, Symbol& inType, bool inLittleEndian, uint32_t inBitSize,
uint32_t inBitOffset)
: symbol{inSymbol}, // @suppress("Symbol is not resolved")
name{inName}, // @suppress("Symbol is not resolved")
byte_offset{inByteOffset},
Expand All @@ -60,13 +61,13 @@ Field::Field(Symbol& inSymbol, std::string& inName, uint32_t inByteOffset, Symbo
}
Field::~Field() {}

uint32_t Field::getByteOffset() const { return byte_offset; }
std::optional<uint32_t> Field::getByteOffset() const { return byte_offset; }

bool Field::isLittleEndian() const { return little_endian; }
bool Field::isLittleEndian() const { return little_endian; }

std::string& Field::getName() { return name; }
std::string& Field::getName() { return name; }

void Field::setName(const std::string& inName)
void Field::setName(const std::string& inName)
{
logger.logDebug("Field %s::%s renamed to %s.", symbol.getName().c_str(), name.c_str(), inName.c_str());

Expand Down
72 changes: 37 additions & 35 deletions src/Field.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include <stdint.h>

#include <optional>
#include <vector>

#include "DimensionList.h"
Expand All @@ -30,50 +31,51 @@ class Field
{
public:
Field(Symbol &symbol, Symbol &type);
Field(Symbol &symbol, std::string &name, uint32_t byte_offset, Symbol &type, DimensionList &dimensionList, bool little_endian, uint32_t inBitSize = 0,
Field(Symbol &symbol, std::string &name, std::optional<uint32_t> byte_offset, Symbol &type, DimensionList &dimensionList, bool little_endian,
uint32_t inBitSize = 0, uint32_t inBitOffset = 0);
Field(Symbol &symbol, std::string &name, std::optional<uint32_t> byte_offset, Symbol &type, bool little_endian, uint32_t inBitSize = 0,
uint32_t inBitOffset = 0);
Field(Symbol &symbol, std::string &name, uint32_t byte_offset, Symbol &type, bool little_endian, uint32_t inBitSize = 0, uint32_t inBitOffset = 0);
virtual ~Field();
uint32_t getByteOffset() const;
bool isLittleEndian() const;
uint32_t getMultiplicity() const;
uint32_t getArraySize() const;
void setMultiplicity(uint32_t multiplicity);
std::string &getName();
void setName(const std::string &name);
Symbol &getSymbol() const;
Symbol &getType();
uint32_t getId(void) const;
void setId(uint32_t newId);
uint32_t getBitOffset() const;
void setBitOffset(uint32_t bitOffset);
uint32_t getBitSize() const;
void setBitSize(uint32_t bitSize);
bool isBitField(void);
DimensionList &getDimensionList();
bool isArray(void) const;
std::string getDimensionListStr();
std::optional<uint32_t> getByteOffset() const;
bool isLittleEndian() const;
uint32_t getMultiplicity() const;
uint32_t getArraySize() const;
void setMultiplicity(uint32_t multiplicity);
std::string &getName();
void setName(const std::string &name);
Symbol &getSymbol() const;
Symbol &getType();
uint32_t getId(void) const;
void setId(uint32_t newId);
uint32_t getBitOffset() const;
void setBitOffset(uint32_t bitOffset);
uint32_t getBitSize() const;
void setBitSize(uint32_t bitSize);
bool isBitField(void);
DimensionList &getDimensionList();
bool isArray(void) const;
std::string getDimensionListStr();

const std::string &getShortDescription() const { return short_description; }
const std::string &getShortDescription() const { return short_description; }

const std::string &getLongDescription() const { return long_description; }
const std::string &getLongDescription() const { return long_description; }

private:
Symbol &symbol;
std::string name;
uint32_t byte_offset;
Symbol &type;
DimensionList dimensionList;
bool little_endian;
Symbol &symbol;
std::string name;
std::optional<uint32_t> byte_offset{std::nullopt};
Symbol &type;
DimensionList dimensionList;
bool little_endian;
/*bit fields members.
* If this field is not bit-packed, then the bit_size and bit_offset are 0.*/
uint32_t bit_offset;
uint32_t bit_size;
Logger logger;
uint32_t id;
uint32_t bit_offset;
uint32_t bit_size;
Logger logger;
uint32_t id;

std::string short_description;
std::string long_description;
std::string short_description;
std::string long_description;
};

#endif /* FIELD_H_ */
14 changes: 7 additions & 7 deletions src/Juicer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4059,7 +4059,7 @@ void Juicer::process_DW_TAG_union_type(ElfFile &elf, Symbol &symbol, Dwarf_Debug
{
std::string sMemberName = memberName;

Field memberField{symbol, sMemberName, (uint32_t)memberLocation, *memberBaseTypeSymbol, dimensionList, elf.isLittleEndian()};
Field memberField{symbol, sMemberName, std::nullopt, *memberBaseTypeSymbol, dimensionList, elf.isLittleEndian()};

addBitFields(memberDie, memberField);
symbol.addField(memberField);
Expand Down Expand Up @@ -4127,9 +4127,9 @@ void Juicer::addPaddingToStruct(Symbol &symbol)
previousFieldSize = symbol.getFields().at(i - 1)->getArraySize() * previousFieldSize;
}

uint32_t lastFieldOffset = symbol.getFields().at(i - 1)->getByteOffset();
uint32_t lastFieldOffset = symbol.getFields().at(i - 1)->getByteOffset().value();

uint32_t memberLocationDelta = symbol.getFields().at(i)->getByteOffset() - lastFieldOffset;
uint32_t memberLocationDelta = symbol.getFields().at(i)->getByteOffset().value() - lastFieldOffset;

uint32_t memberLocation = lastFieldOffset + previousFieldSize;

Expand Down Expand Up @@ -4192,12 +4192,12 @@ void Juicer::addPaddingEndToStruct(Symbol &symbol)

if (!hasBitFields && symbol.getFields().size() > 0)
{
symbolSize = symbol.getFields().back()->getByteOffset() + symbol.getFields().back()->getType().getByteSize();
symbolSize = symbol.getFields().back()->getByteOffset().value() + symbol.getFields().back()->getType().getByteSize();

if (symbol.getFields().back()->getArraySize() > 0)
{
symbolSize =
symbol.getFields().back()->getByteOffset() + (symbol.getFields().back()->getType().getByteSize() * symbol.getFields().back()->getArraySize());
symbolSize = symbol.getFields().back()->getByteOffset().value() +
(symbol.getFields().back()->getType().getByteSize() * symbol.getFields().back()->getArraySize());
}

sizeDelta = symbol.getByteSize() - symbolSize;
Expand All @@ -4218,7 +4218,7 @@ void Juicer::addPaddingEndToStruct(Symbol &symbol)
paddingSymbol = symbol.getElf().addSymbol(paddingType, sizeDelta, newArtifact);
}

uint32_t newFieldByteOffset = symbol.getFields().back()->getByteOffset() + symbol.getFields().back()->getType().getByteSize();
uint32_t newFieldByteOffset = symbol.getFields().back()->getByteOffset().value() + symbol.getFields().back()->getType().getByteSize();

symbol.addField(paddingFieldName, newFieldByteOffset, *paddingSymbol, symbol.getElf().isLittleEndian(), 0, 0);
}
Expand Down
108 changes: 73 additions & 35 deletions src/SQLiteDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1354,41 +1354,79 @@ int SQLiteDB::writeFieldsToDatabase(ElfFile& inElf)
* but I'm not sure what is the best way to do that without it being
* messy.
*/
std::string writeFieldQuery{};

writeFieldQuery +=
"INSERT INTO fields(symbol, name, byte_offset, type, "
"little_endian, bit_size, bit_offset, long_description, short_description) VALUES(";
writeFieldQuery += std::to_string(field->getSymbol().getId());
writeFieldQuery += ",";
writeFieldQuery += "\"";
writeFieldQuery += field->getName();
writeFieldQuery += "\"";
writeFieldQuery += ",";
writeFieldQuery += std::to_string(field->getByteOffset());
writeFieldQuery += ",";
writeFieldQuery += std::to_string(field->getType().getId());
writeFieldQuery += ",";
writeFieldQuery += std::to_string(field->isLittleEndian() ? SQLiteDB_TRUE : SQLiteDB_FALSE);

writeFieldQuery += ",";
writeFieldQuery += std::to_string(field->getBitSize());
writeFieldQuery += ",";
writeFieldQuery += std::to_string(field->getBitOffset());

writeFieldQuery += ",";
writeFieldQuery += "\"";
writeFieldQuery += field->getLongDescription();
writeFieldQuery += "\"";

writeFieldQuery += ",";
writeFieldQuery += "\"";
writeFieldQuery += field->getShortDescription();
writeFieldQuery += "\"";

writeFieldQuery += ");";

rc = sqlite3_exec(database, writeFieldQuery.c_str(), NULL, NULL, &errorMessage);
std::string writeFieldQuery{};

std::optional<uint32_t> byteOffset = field->getByteOffset();

if (byteOffset)
{
writeFieldQuery +=
"INSERT INTO fields(symbol, name, byte_offset, type, "
"little_endian, bit_size, bit_offset, long_description, short_description) VALUES(";
writeFieldQuery += std::to_string(field->getSymbol().getId());
writeFieldQuery += ",";
writeFieldQuery += "\"";
writeFieldQuery += field->getName();
writeFieldQuery += "\"";
writeFieldQuery += ",";
writeFieldQuery += std::to_string(field->getByteOffset().value());
writeFieldQuery += ",";
writeFieldQuery += std::to_string(field->getType().getId());
writeFieldQuery += ",";
writeFieldQuery += std::to_string(field->isLittleEndian() ? SQLiteDB_TRUE : SQLiteDB_FALSE);

writeFieldQuery += ",";
writeFieldQuery += std::to_string(field->getBitSize());
writeFieldQuery += ",";
writeFieldQuery += std::to_string(field->getBitOffset());

writeFieldQuery += ",";
writeFieldQuery += "\"";
writeFieldQuery += field->getLongDescription();
writeFieldQuery += "\"";

writeFieldQuery += ",";
writeFieldQuery += "\"";
writeFieldQuery += field->getShortDescription();
writeFieldQuery += "\"";

writeFieldQuery += ");";
}

else
{
writeFieldQuery +=
"INSERT INTO fields(symbol, name, type, "
"little_endian, bit_size, bit_offset, long_description, short_description) VALUES(";
writeFieldQuery += std::to_string(field->getSymbol().getId());
writeFieldQuery += ",";
writeFieldQuery += "\"";
writeFieldQuery += field->getName();
writeFieldQuery += "\"";
writeFieldQuery += ",";
writeFieldQuery += std::to_string(field->getType().getId());
writeFieldQuery += ",";
writeFieldQuery += std::to_string(field->isLittleEndian() ? SQLiteDB_TRUE : SQLiteDB_FALSE);

writeFieldQuery += ",";
writeFieldQuery += std::to_string(field->getBitSize());
writeFieldQuery += ",";
writeFieldQuery += std::to_string(field->getBitOffset());

writeFieldQuery += ",";
writeFieldQuery += "\"";
writeFieldQuery += field->getLongDescription();
writeFieldQuery += "\"";

writeFieldQuery += ",";
writeFieldQuery += "\"";
writeFieldQuery += field->getShortDescription();
writeFieldQuery += "\"";

writeFieldQuery += ");";
}

rc = sqlite3_exec(database, writeFieldQuery.c_str(), NULL, NULL, &errorMessage);

if (SQLITE_OK == rc)
{
Expand Down
2 changes: 1 addition & 1 deletion src/SQLiteDB.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
id INTEGER PRIMARY KEY,\
symbol INTEGER NOT NULL,\
name TEXT NOT NULL,\
byte_offset INTEGER NOT NULL,\
byte_offset INTEGER,\
type INTEGER NOT NULL,\
little_endian BOOLEAN,\
bit_size INTEGER NOT NULL,\
Expand Down
4 changes: 2 additions & 2 deletions src/Symbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ void Symbol::addField(Field& inField)
*unique_ptr, which is also called addField. Maybe we should place our
*elf data structures inside a namespace called ElfData?
*/
void Symbol::addField(std::string& inName, uint32_t inByteOffset, Symbol& inType, DimensionList& dimensionList, bool inLittleEndian, uint32_t inBitSize,
uint32_t inBitOffset)
void Symbol::addField(std::string& inName, std::optional<uint32_t> inByteOffset, Symbol& inType, DimensionList& dimensionList, bool inLittleEndian,
uint32_t inBitSize, uint32_t inBitOffset)
{
Field* field = getField(inName);

Expand Down
4 changes: 2 additions & 2 deletions src/Symbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ class Symbol
uint32_t getId(void) const;
Symbol(const Symbol &symbol);
void addField(Field &inField);
void addField(std::string &inName, uint32_t inByteOffset, Symbol &inType, DimensionList &dimensionList, bool inLittleEndian, uint32_t inBitSize = 0,
uint32_t inBitOffset = 0);
void addField(std::string &inName, std::optional<uint32_t> inByteOffset, Symbol &inType, DimensionList &dimensionList, bool inLittleEndian,
uint32_t inBitSize = 0, uint32_t inBitOffset = 0);
void addField(std::string &inName, uint32_t inByteOffset, Symbol &inType, bool inLittleEndian, uint32_t inBitSize = 0, uint32_t inBitOffset = 0);
void addEnumeration(Enumeration &inEnumeration);
void addEnumeration(std::string &name, int32_t value);
Expand Down

0 comments on commit bdd9546

Please sign in to comment.