From b2f6c14ce426a24091e1da11e9a03cdf075c4998 Mon Sep 17 00:00:00 2001 From: lgomez Date: Fri, 10 Jan 2025 17:33:21 -0600 Subject: [PATCH] -Link namespaces to symbols. WIP. -Add unit testing for namespacing. WIP. --- src/ElfFile.cpp | 5 +- src/ElfFile.h | 38 +++--- src/Juicer.cpp | 92 +++++++------- src/Juicer.h | 16 +-- src/SQLiteDB.cpp | 59 +++++++-- src/SQLiteDB.h | 2 + src/Symbol.h | 7 ++ unit-test/main_test.cpp | 220 +++++++++++++++++++++++++++++++++- unit-test/namespaces_test.cpp | 47 +++++++- 9 files changed, 395 insertions(+), 91 deletions(-) diff --git a/src/ElfFile.cpp b/src/ElfFile.cpp index 2f5c9ebf..b1415eb0 100644 --- a/src/ElfFile.cpp +++ b/src/ElfFile.cpp @@ -85,7 +85,7 @@ Symbol* ElfFile::getSymbol(std::string& name) return returnSymbol; } -Symbol* ElfFile::addSymbol(std::string& inName, uint32_t inByteSize, Artifact newArtifact, Symbol* targetSymbol) +Symbol* ElfFile::addSymbol(std::string& inName, uint32_t inByteSize, Artifact newArtifact, Symbol* targetSymbol, Namespace* symbolNamepace) { Symbol* symbol = getSymbol(inName); @@ -102,13 +102,14 @@ Symbol* ElfFile::addSymbol(std::string& inName, uint32_t inByteSize, Artifact ne return symbol; } -Symbol* ElfFile::addSymbol(std::string& inName, uint32_t inByteSize, Artifact newArtifact) +Symbol* ElfFile::addSymbol(std::string& inName, uint32_t inByteSize, Artifact newArtifact, Namespace* symbolNamepace) { Symbol* symbol = getSymbol(inName); if (symbol == nullptr) { std::unique_ptr newSymbol = std::make_unique(*this, inName, inByteSize, newArtifact); + newSymbol->setNamespace(symbolNamepace); symbols.push_back(std::move(newSymbol)); diff --git a/src/ElfFile.h b/src/ElfFile.h index 3907fdf3..dc8c259e 100644 --- a/src/ElfFile.h +++ b/src/ElfFile.h @@ -48,25 +48,25 @@ class ElfFile public: ElfFile(std::string &name); virtual ~ElfFile(); - std::vector> &getSymbols(); - - std::string getName() const; - uint32_t getId(void) const; - void setId(uint32_t newId); - Symbol *addSymbol(std::string &name, uint32_t byte_size, Artifact newArtifact); - Symbol *addSymbol(std::string &inName, uint32_t inByteSize, Artifact newArtifact, Symbol *targetSymbol); - std::vector getFields(); - std::vector getEnumerations(); - Symbol *getSymbol(std::string &name); - const std::string &getDate() const; - void setDate(const std::string &date); - bool isLittleEndian() const; - void isLittleEndian(bool littleEndian); - void setMD5(std::string newID); - std::string getMD5() const; - void addDefineMacro(DefineMacro newMacro); - - const std::vector &getDefineMacros() const; + std::vector> &getSymbols(); + + std::string getName() const; + uint32_t getId(void) const; + void setId(uint32_t newId); + Symbol *addSymbol(std::string &name, uint32_t byte_size, Artifact newArtifact, Namespace *symbolNamepace); + Symbol *addSymbol(std::string &inName, uint32_t inByteSize, Artifact newArtifact, Symbol *targetSymbol, Namespace *symbolNamepace); + std::vector getFields(); + std::vector getEnumerations(); + Symbol *getSymbol(std::string &name); + const std::string &getDate() const; + void setDate(const std::string &date); + bool isLittleEndian() const; + void isLittleEndian(bool littleEndian); + void setMD5(std::string newID); + std::string getMD5() const; + void addDefineMacro(DefineMacro newMacro); + + const std::vector &getDefineMacros() const; const std::map> &getInitializedSymbolData() const; diff --git a/src/Juicer.cpp b/src/Juicer.cpp index 86490f28..a2e9e654 100644 --- a/src/Juicer.cpp +++ b/src/Juicer.cpp @@ -449,7 +449,7 @@ char *Juicer::dwarfStringToChar(char *dwarfString) * it does NOT mean that no array was found. There are cases where an array is found on the die, * however, because it has no name we decide to not add it to the elf at all. */ -int Juicer::process_DW_TAG_array_type(ElfFile &elf, Symbol &symbol, Dwarf_Debug dbg, Dwarf_Die inDie) +int Juicer::process_DW_TAG_array_type(ElfFile &elf, Symbol &symbol, Dwarf_Debug dbg, Dwarf_Die inDie, Namespace *currentNamespace) { Dwarf_Die dieSubrangeType; Dwarf_Unsigned dwfUpperBound = 0; @@ -538,7 +538,7 @@ int Juicer::process_DW_TAG_array_type(ElfFile &elf, Symbol &symbol, Dwarf_Debug */ std::string stdString{arrayName}; - Symbol *arraySymbol = getBaseTypeSymbol(elf, inDie, dimList); + Symbol *arraySymbol = getBaseTypeSymbol(elf, inDie, dimList, currentNamespace); if (nullptr == arraySymbol) { @@ -715,7 +715,7 @@ Namespace *Juicer::process_DW_TAG_namespace(ElfFile &elf, Dwarf_Debug dbg, Dwarf return newParentNamespace; } -Symbol *Juicer::process_DW_TAG_pointer_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die inDie) +Symbol *Juicer::process_DW_TAG_pointer_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die inDie, Namespace *currentNamespace) { Symbol *outSymbol = 0; Dwarf_Attribute attr_struct = nullptr; @@ -786,7 +786,7 @@ Symbol *Juicer::process_DW_TAG_pointer_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf Artifact newArtifact{elf, getdbgSourceFile(elf, pathIndex).value_or(std::string{"NOT_FOUND:"})}; std::string checkSum = generateMD5SumForFile(newArtifact.getFilePath()); newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(voidType, byteSize, newArtifact); + outSymbol = elf.addSymbol(voidType, byteSize, newArtifact, nullptr); } else { @@ -795,7 +795,7 @@ Symbol *Juicer::process_DW_TAG_pointer_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf Artifact newArtifact{elf, "NOT_FOUND:" + voidType}; std::string checkSum{}; newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(voidType, byteSize, newArtifact); + outSymbol = elf.addSymbol(voidType, byteSize, newArtifact, nullptr); } } } @@ -863,14 +863,14 @@ Symbol *Juicer::process_DW_TAG_pointer_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf Artifact newArtifact{elf, "NOT_FOUND:" + name}; std::string checkSum{}; newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(name, byteSize, newArtifact); + outSymbol = elf.addSymbol(name, byteSize, newArtifact, currentNamespace); } } return outSymbol; } -Symbol *Juicer::process_DW_TAG_variable_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die inDie) +Symbol *Juicer::process_DW_TAG_variable_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die inDie, Namespace *currentNamespace) { Symbol *outSymbol = 0; Dwarf_Attribute attr_struct = nullptr; @@ -960,7 +960,7 @@ Symbol *Juicer::process_DW_TAG_variable_type(ElfFile &elf, Dwarf_Debug dbg, Dwar DimensionList dimList{}; // TODO:Really don't like the pattern of passing an empty object to getBaseTypeSymbol... - Symbol *s = getBaseTypeSymbol(elf, inDie, dimList); + Symbol *s = getBaseTypeSymbol(elf, inDie, dimList, currentNamespace); if (s != nullptr) { @@ -990,7 +990,7 @@ Symbol *Juicer::process_DW_TAG_variable_type(ElfFile &elf, Dwarf_Debug dbg, Dwar return outSymbol; } -Symbol *Juicer::getBaseTypeSymbol(ElfFile &elf, Dwarf_Die inDie, DimensionList &dimList) +Symbol *Juicer::getBaseTypeSymbol(ElfFile &elf, Dwarf_Die inDie, DimensionList &dimList, Namespace *currentNamespace) { int res = DW_DLV_OK; Dwarf_Attribute attr_struct; @@ -1047,7 +1047,7 @@ Symbol *Juicer::getBaseTypeSymbol(ElfFile &elf, Dwarf_Die inDie, DimensionList & { case DW_TAG_pointer_type: { - outSymbol = process_DW_TAG_pointer_type(elf, dbg, typeDie); + outSymbol = process_DW_TAG_pointer_type(elf, dbg, typeDie, currentNamespace); break; } @@ -1175,20 +1175,20 @@ Symbol *Juicer::getBaseTypeSymbol(ElfFile &elf, Dwarf_Die inDie, DimensionList & Artifact newArtifact{elf, getdbgSourceFile(elf, pathIndex).value_or(std::string{"NOT_FOUND:"})}; std::string checkSum = generateMD5SumForFile(newArtifact.getFilePath()); newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(cName, byteSize, newArtifact); + outSymbol = elf.addSymbol(cName, byteSize, newArtifact, currentNamespace); } else { Artifact newArtifact{elf, "NOT_FOUND:" + cName}; std::string checkSum{}; newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(cName, byteSize, newArtifact); + outSymbol = elf.addSymbol(cName, byteSize, newArtifact, currentNamespace); } } if (nullptr != outSymbol) { - process_DW_TAG_structure_type(elf, *outSymbol, dbg, typeDie); + process_DW_TAG_structure_type(elf, *outSymbol, dbg, typeDie, currentNamespace); } } else @@ -1199,20 +1199,20 @@ Symbol *Juicer::getBaseTypeSymbol(ElfFile &elf, Dwarf_Die inDie, DimensionList & Artifact newArtifact{elf, "NOT_FOUND:" + cName}; std::string checkSum{}; newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(cName, byteSize, newArtifact); + outSymbol = elf.addSymbol(cName, byteSize, newArtifact, currentNamespace); } break; } case DW_TAG_base_type: { - outSymbol = process_DW_TAG_base_type(elf, dbg, typeDie); + outSymbol = process_DW_TAG_base_type(elf, dbg, typeDie, currentNamespace); break; } case DW_TAG_typedef: { - outSymbol = process_DW_TAG_typedef(elf, dbg, typeDie); + outSymbol = process_DW_TAG_typedef(elf, dbg, typeDie, currentNamespace); break; } @@ -1348,14 +1348,14 @@ Symbol *Juicer::getBaseTypeSymbol(ElfFile &elf, Dwarf_Die inDie, DimensionList & Artifact newArtifact{elf, getdbgSourceFile(elf, pathIndex).value_or(std::string{"NOT_FOUND:"})}; std::string checkSum = generateMD5SumForFile(newArtifact.getFilePath()); newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(cName, byteSize, newArtifact); + outSymbol = elf.addSymbol(cName, byteSize, newArtifact, currentNamespace); } else { Artifact newArtifact{elf, "NOT_FOUND:" + cName}; std::string checkSum{}; newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(cName, byteSize, newArtifact); + outSymbol = elf.addSymbol(cName, byteSize, newArtifact, currentNamespace); } } @@ -1364,7 +1364,7 @@ Symbol *Juicer::getBaseTypeSymbol(ElfFile &elf, Dwarf_Die inDie, DimensionList & Artifact newArtifact{elf, "NOT_FOUND:" + cName}; std::string checkSum{}; newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(cName, byteSize, newArtifact); + outSymbol = elf.addSymbol(cName, byteSize, newArtifact, currentNamespace); } process_DW_TAG_enumeration_type(elf, *outSymbol, dbg, typeDie); @@ -1376,7 +1376,7 @@ Symbol *Juicer::getBaseTypeSymbol(ElfFile &elf, Dwarf_Die inDie, DimensionList & { /* First get the base type itself. */ - outSymbol = getBaseTypeSymbol(elf, typeDie, dimList); + outSymbol = getBaseTypeSymbol(elf, typeDie, dimList, currentNamespace); /* Set the multiplicity argument. */ if (res == DW_DLV_OK) @@ -1399,7 +1399,7 @@ Symbol *Juicer::getBaseTypeSymbol(ElfFile &elf, Dwarf_Die inDie, DimensionList & /* Get the type attribute. */ res = dwarf_attr(inDie, DW_AT_type, &attr_struct, &error); - getBaseTypeSymbol(elf, typeDie, dimList); + getBaseTypeSymbol(elf, typeDie, dimList, currentNamespace); break; } @@ -1513,20 +1513,20 @@ Symbol *Juicer::getBaseTypeSymbol(ElfFile &elf, Dwarf_Die inDie, DimensionList & Artifact newArtifact{elf, getdbgSourceFile(elf, pathIndex).value_or(std::string{"NOT_FOUND:"})}; std::string checkSum = generateMD5SumForFile(newArtifact.getFilePath()); newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(cName, byteSize, newArtifact); + outSymbol = elf.addSymbol(cName, byteSize, newArtifact, currentNamespace); } else { Artifact newArtifact{elf, "NOT_FOUND:" + cName}; std::string checkSum{}; newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(cName, byteSize, newArtifact); + outSymbol = elf.addSymbol(cName, byteSize, newArtifact, currentNamespace); } } if (nullptr != outSymbol) { - process_DW_TAG_union_type(elf, *outSymbol, dbg, typeDie); + process_DW_TAG_union_type(elf, *outSymbol, dbg, typeDie, currentNamespace); } } @@ -3308,7 +3308,7 @@ void Juicer::DisplayDie(Dwarf_Die inDie, uint32_t level) // } } -Symbol *Juicer::process_DW_TAG_base_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die inDie) +Symbol *Juicer::process_DW_TAG_base_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die inDie, Namespace *currentNamespace) { int res = DW_DLV_OK; Dwarf_Unsigned byteSize = 0; @@ -3434,14 +3434,14 @@ Symbol *Juicer::process_DW_TAG_base_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Di Artifact newArtifact{elf, getdbgSourceFile(elf, pathIndex).value_or(std::string{"NOT_FOUND:"})}; std::string checkSum = generateMD5SumForFile(newArtifact.getFilePath()); newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact); + outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact, currentNamespace); } else { Artifact newArtifact{elf, "NOT_FOUND:" + sDieName}; std::string checkSum{}; newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact); + outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact, currentNamespace); } } @@ -3453,7 +3453,7 @@ Symbol *Juicer::process_DW_TAG_base_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Di Artifact newArtifact{elf, "NOT_FOUND:" + cName}; std::string checkSum{}; newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(cName, byteSize, newArtifact); + outSymbol = elf.addSymbol(cName, byteSize, newArtifact, currentNamespace); } } } @@ -3624,7 +3624,7 @@ void Juicer::process_DW_TAG_enumeration_type(ElfFile &elf, Symbol &symbol, Dwarf * @return 0 if the die, its children and siblings are scanned successfully. * 1 if there is a problem with dies or any of its children. */ -Symbol *Juicer::process_DW_TAG_typedef(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die inDie) +Symbol *Juicer::process_DW_TAG_typedef(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die inDie, Namespace *currentNamespace) { int res = DW_DLV_OK; uint32_t byteSize = 0; @@ -3658,7 +3658,7 @@ Symbol *Juicer::process_DW_TAG_typedef(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die { DimensionList dimensionList{}; - baseTypeSymbol = getBaseTypeSymbol(elf, inDie, dimensionList); + baseTypeSymbol = getBaseTypeSymbol(elf, inDie, dimensionList, currentNamespace); if (baseTypeSymbol == 0) { @@ -3724,14 +3724,14 @@ Symbol *Juicer::process_DW_TAG_typedef(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die Artifact newArtifact{elf, getdbgSourceFile(elf, pathIndex).value_or(std::string{"NOT_FOUND:"})}; std::string checkSum = generateMD5SumForFile(newArtifact.getFilePath()); newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact, baseTypeSymbol); + outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact, baseTypeSymbol, currentNamespace); } else { Artifact newArtifact{elf, "NOT_FOUND:" + sDieName}; std::string checkSum{}; newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact, baseTypeSymbol); + outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact, baseTypeSymbol, currentNamespace); } } } @@ -3746,7 +3746,7 @@ Symbol *Juicer::process_DW_TAG_typedef(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die * @return 0 if the die, its children and siblings are scanned successfully. * 1 if there is a problem with dies or any of its children. */ -void Juicer::process_DW_TAG_structure_type(ElfFile &elf, Symbol &symbol, Dwarf_Debug dbg, Dwarf_Die inDie) +void Juicer::process_DW_TAG_structure_type(ElfFile &elf, Symbol &symbol, Dwarf_Debug dbg, Dwarf_Die inDie, Namespace *currentNamespace) { int res = DW_DLV_OK; Dwarf_Attribute attr_struct = nullptr; @@ -3978,7 +3978,7 @@ void Juicer::process_DW_TAG_structure_type(ElfFile &elf, Symbol &symbol, Dwarf_D /* Get the base type die. */ if (res == DW_DLV_OK) { - memberBaseTypeSymbol = getBaseTypeSymbol(elf, memberDie, dimensionList); + memberBaseTypeSymbol = getBaseTypeSymbol(elf, memberDie, dimensionList, currentNamespace); if (memberBaseTypeSymbol == 0) { @@ -4048,7 +4048,7 @@ void Juicer::process_DW_TAG_structure_type(ElfFile &elf, Symbol &symbol, Dwarf_D * @return 0 if the die, its children and siblings are scanned successfully. * 1 if there is a problem with dies or any of its children. */ -void Juicer::process_DW_TAG_union_type(ElfFile &elf, Symbol &symbol, Dwarf_Debug dbg, Dwarf_Die inDie) +void Juicer::process_DW_TAG_union_type(ElfFile &elf, Symbol &symbol, Dwarf_Debug dbg, Dwarf_Die inDie, Namespace *currentNamespace) { int res = DW_DLV_OK; Dwarf_Attribute attr_struct = nullptr; @@ -4137,7 +4137,7 @@ void Juicer::process_DW_TAG_union_type(ElfFile &elf, Symbol &symbol, Dwarf_Debug /* Get the base type die. */ if (res == DW_DLV_OK) { - memberBaseTypeSymbol = getBaseTypeSymbol(elf, memberDie, dimensionList); + memberBaseTypeSymbol = getBaseTypeSymbol(elf, memberDie, dimensionList, currentNamespace); if (memberBaseTypeSymbol == 0) { @@ -4253,7 +4253,7 @@ void Juicer::addPaddingToStruct(Symbol &symbol) std::string checkSum = generateMD5SumForFile(newArtifact.getFilePath()); newArtifact.setMD5(checkSum); - paddingSymbol = symbol.getElf().addSymbol(paddingType, paddingSize, newArtifact); + paddingSymbol = symbol.getElf().addSymbol(paddingType, paddingSize, newArtifact, nullptr); } auto &&fields = symbol.getFields(); @@ -4315,7 +4315,7 @@ void Juicer::addPaddingEndToStruct(Symbol &symbol) Artifact newArtifact{symbol.getElf(), symbol.getArtifact().getFilePath()}; std::string checkSum = generateMD5SumForFile(newArtifact.getFilePath()); newArtifact.setMD5(checkSum); - paddingSymbol = symbol.getElf().addSymbol(paddingType, sizeDelta, newArtifact); + paddingSymbol = symbol.getElf().addSymbol(paddingType, sizeDelta, newArtifact, (Namespace *)nullptr); } uint32_t newFieldByteOffset = symbol.getFields().back()->getByteOffset().value() + symbol.getFields().back()->getType().getByteSize(); @@ -4451,14 +4451,14 @@ int Juicer::getDieAndSiblings(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die in_die, i { case DW_TAG_base_type: { - process_DW_TAG_base_type(elf, dbg, cur_die); + process_DW_TAG_base_type(elf, dbg, cur_die, currentNamespace); break; } case DW_TAG_typedef: { - process_DW_TAG_typedef(elf, dbg, cur_die); + process_DW_TAG_typedef(elf, dbg, cur_die, currentNamespace); break; } @@ -4523,14 +4523,14 @@ int Juicer::getDieAndSiblings(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die in_die, i Artifact newArtifact{elf, getdbgSourceFile(elf, pathIndex).value_or(std::string{"NOT_FOUND:"})}; std::string checkSum = generateMD5SumForFile(newArtifact.getFilePath()); newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact); + outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact, currentNamespace); } else { Artifact newArtifact{elf, "NOT_FOUND:" + sDieName}; std::string checkSum{}; newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact); + outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact, currentNamespace); } } else @@ -4538,10 +4538,10 @@ int Juicer::getDieAndSiblings(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die in_die, i Artifact newArtifact{elf, "NOT_FOUND:" + sDieName}; std::string checkSum{}; newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact); + outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact, currentNamespace); } - process_DW_TAG_structure_type(elf, *outSymbol, dbg, cur_die); + process_DW_TAG_structure_type(elf, *outSymbol, dbg, cur_die, currentNamespace); } } @@ -4551,7 +4551,7 @@ int Juicer::getDieAndSiblings(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die in_die, i { Symbol s{elf}; - res = process_DW_TAG_array_type(elf, s, dbg, cur_die); + res = process_DW_TAG_array_type(elf, s, dbg, cur_die, currentNamespace); break; } @@ -4560,7 +4560,7 @@ int Juicer::getDieAndSiblings(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die in_die, i { if (extras) { - process_DW_TAG_variable_type(elf, dbg, cur_die); + process_DW_TAG_variable_type(elf, dbg, cur_die, currentNamespace); } break; } diff --git a/src/Juicer.h b/src/Juicer.h index 9d67d7a3..005648eb 100644 --- a/src/Juicer.h +++ b/src/Juicer.h @@ -113,14 +113,14 @@ class Juicer Dwarf_Ptr errarg = 0; int readCUList(ElfFile& elf, Dwarf_Debug dbg, Dwarf_Error& error); int getDieAndSiblings(ElfFile& elf, Dwarf_Debug dbg, Dwarf_Die in_die, int in_level, Namespace* currentNamespace); - Symbol* process_DW_TAG_typedef(ElfFile& elf, Dwarf_Debug dbg, Dwarf_Die in_die); - Symbol* process_DW_TAG_base_type(ElfFile& elf, Dwarf_Debug dbg, Dwarf_Die in_die); - void process_DW_TAG_structure_type(ElfFile& elf, Symbol& symbol, Dwarf_Debug dbg, Dwarf_Die inDie); - Symbol* process_DW_TAG_pointer_type(ElfFile& elf, Dwarf_Debug dbg, Dwarf_Die inDie); - Symbol* process_DW_TAG_variable_type(ElfFile& elf, Dwarf_Debug dbg, Dwarf_Die inDie); + Symbol* process_DW_TAG_typedef(ElfFile& elf, Dwarf_Debug dbg, Dwarf_Die in_die, Namespace* currentNamespace); + Symbol* process_DW_TAG_base_type(ElfFile& elf, Dwarf_Debug dbg, Dwarf_Die in_die, Namespace* currentNamespace); + void process_DW_TAG_structure_type(ElfFile& elf, Symbol& symbol, Dwarf_Debug dbg, Dwarf_Die inDie, Namespace* currentNamespace); + Symbol* process_DW_TAG_pointer_type(ElfFile& elf, Dwarf_Debug dbg, Dwarf_Die inDie, Namespace* currentNamespace); + Symbol* process_DW_TAG_variable_type(ElfFile& elf, Dwarf_Debug dbg, Dwarf_Die inDie, Namespace* currentNamespace); void process_DW_TAG_enumeration_type(ElfFile& elf, Symbol& symbol, Dwarf_Debug dbg, Dwarf_Die inDie); - int process_DW_TAG_array_type(ElfFile& elf, Symbol& symbol, Dwarf_Debug dbg, Dwarf_Die inDie); - void process_DW_TAG_union_type(ElfFile& elf, Symbol& symbol, Dwarf_Debug dbg, Dwarf_Die inDie); + int process_DW_TAG_array_type(ElfFile& elf, Symbol& symbol, Dwarf_Debug dbg, Dwarf_Die inDie, Namespace* currentNamespace); + void process_DW_TAG_union_type(ElfFile& elf, Symbol& symbol, Dwarf_Debug dbg, Dwarf_Die inDie, Namespace* currentNamespace); Namespace* process_DW_TAG_namespace(ElfFile& elf, Dwarf_Debug dbg, Dwarf_Die inDie, int in_level, Namespace* currentNamespace); char* getFirstAncestorName(Dwarf_Die inDie); int printDieData(Dwarf_Debug dbg, Dwarf_Die print_me, uint32_t level); @@ -133,7 +133,7 @@ class Juicer Logger logger; IDataContainer* idc = 0; bool isIDCSet(void); - Symbol* getBaseTypeSymbol(ElfFile& elf, Dwarf_Die inDie, DimensionList& multiplicity); + Symbol* getBaseTypeSymbol(ElfFile& elf, Dwarf_Die inDie, DimensionList& dimList, Namespace* currentNamespace); void DisplayDie(Dwarf_Die inDie, uint32_t level); std::vector getChildrenVector(Dwarf_Debug dbg, Dwarf_Die die); diff --git a/src/SQLiteDB.cpp b/src/SQLiteDB.cpp index 5d3f9db8..b663ac7b 100644 --- a/src/SQLiteDB.cpp +++ b/src/SQLiteDB.cpp @@ -315,7 +315,7 @@ int SQLiteDB::write(ElfFile& inElf) else { logger.logDebug( - "There was an error while writing macro entries to the" + "There was an error while writing Artifact entries to the" " database."); rc = SQLITEDB_ERROR; } @@ -333,13 +333,29 @@ int SQLiteDB::write(ElfFile& inElf) if (SQLITEDB_ERROR != rc) { logger.logDebug( - "Variable entries were written to the variables schema " + "Encoding entries were written to the Encodings schema " "with SQLITE_OK status."); + + rc = writeAllNamespacesToDatabase(inElf); + + if (SQLITEDB_ERROR != rc) + { + logger.logDebug( + "Namespace entries were written to the namespaces schema " + "with SQLITE_OK status."); + } + else + { + logger.logDebug( + "There was an error while writing namespace entries to the" + " database."); + rc = SQLITEDB_ERROR; + } } else { logger.logDebug( - "There was an error while writing variable entries to the" + "There was an error while writing Encoding entries to the" " database."); rc = SQLITEDB_ERROR; } @@ -354,14 +370,28 @@ int SQLiteDB::write(ElfFile& inElf) rc = writeFieldsToDatabase(inElf); - writeDimensionsListToDatabase(inElf); - if (SQLITEDB_ERROR != rc) { logger.logDebug( "Field entries were written to the fields schema " "with SQLITE_OK status."); + rc = writeDimensionsListToDatabase(inElf); + + if (SQLITEDB_ERROR != rc) + { + logger.logDebug( + "Field entries were written to the dimension_lists schema " + "with SQLITE_OK status."); + } + else + { + logger.logDebug( + "There was an error while writing dimension_lists entries to the" + " database."); + rc = SQLITEDB_ERROR; + } + rc = writeEnumerationsToDatabase(inElf); if (SQLITEDB_ERROR != rc) @@ -383,7 +413,7 @@ int SQLiteDB::write(ElfFile& inElf) if (SQLITEDB_ERROR != rc) { logger.logDebug( - "Variable entries were written to the variables schema " + "Elf Sections were written to the variables schema " "with SQLITE_OK status."); rc = writeElfSymboltableSymbolsToDatabase(inElf); @@ -391,10 +421,8 @@ int SQLiteDB::write(ElfFile& inElf) if (SQLITEDB_ERROR != rc) { logger.logDebug( - "Variable entries were written to the variables schema " + "Elf Symbol Table Symbols entries were written to the variables schema " "with SQLITE_OK status."); - - rc = writeAllNamespacesToDatabase(inElf); } else { @@ -1184,7 +1212,7 @@ int SQLiteDB::writeSymbolsToDatabase(ElfFile& inElf) if (!symbol->getEncoding()) { writeSymbolQuery += - "INSERT INTO symbols(elf, name, byte_size, artifact, long_description, short_description) " + "INSERT INTO symbols(elf, name, byte_size, artifact, namespace, long_description, short_description) " "VALUES("; writeSymbolQuery += std::to_string(symbol->getElf().getId()); writeSymbolQuery += ",\""; @@ -1195,6 +1223,17 @@ int SQLiteDB::writeSymbolsToDatabase(ElfFile& inElf) writeSymbolQuery += ","; writeSymbolQuery += std::to_string(symbol->getArtifact().getId()); + writeSymbolQuery += ","; + + if (symbol->getNamespace() != nullptr) + { + writeSymbolQuery += std::to_string(symbol->getNamespace()->getId().value()); + } + else + { + writeSymbolQuery += "-1"; + } + writeSymbolQuery += ",\""; writeSymbolQuery += symbol->getLongDescription(); diff --git a/src/SQLiteDB.h b/src/SQLiteDB.h index a4216f69..1632abec 100644 --- a/src/SQLiteDB.h +++ b/src/SQLiteDB.h @@ -42,12 +42,14 @@ artifact INTEGER,\ target_symbol INTEGER,\ encoding INTEGER,\ + namespace INTEGER,\ short_description TEXT ,\ long_description TEXT ,\ FOREIGN KEY(elf) REFERENCES elfs(id),\ FOREIGN KEY(artifact) REFERENCES artifacts(id)\ FOREIGN KEY(target_symbol) REFERENCES symbols(id)\ FOREIGN KEY(encoding) REFERENCES encodings(id)\ + FOREIGN KEY(namespace) REFERENCES namespaces(id)\ UNIQUE(name));" #define CREATE_DIMENSION_TABLE \ diff --git a/src/Symbol.h b/src/Symbol.h index 53246be4..327595f7 100644 --- a/src/Symbol.h +++ b/src/Symbol.h @@ -20,6 +20,7 @@ #include "Enumeration.h" #include "Field.h" #include "Logger.h" +#include "Namespace.hpp" class Field; class Enumeration; @@ -73,6 +74,10 @@ class Symbol std::optional getEncoding(); + void setNamespace(Namespace *newNamespace) { namespace_ = newNamespace; } + + Namespace *getNamespace() { return namespace_; } + private: ElfFile &elf; std::string name; @@ -88,6 +93,8 @@ class Symbol std::string long_description; std::optional encoding{std::nullopt}; + + Namespace *namespace_{nullptr}; }; #endif /* SYMBOL_H_ */ diff --git a/unit-test/main_test.cpp b/unit-test/main_test.cpp index e18eab81..f85a68a9 100644 --- a/unit-test/main_test.cpp +++ b/unit-test/main_test.cpp @@ -29,6 +29,8 @@ #define TEST_FILE_4 "ut_obj/macro_test.o" +#define TEST_FILE_5 "ut_obj/namespaces_test.o" + // DO NOT rename this macro to something like SQLITE_NULL as that is a macro that exists in sqlite3 #define TEST_NULL_STR "NULL" @@ -1119,7 +1121,7 @@ TEST_CASE("Test the correctness of the Square struct after Juicer has processed numberOfColumns++; } - REQUIRE(numberOfColumns == 9); + REQUIRE(numberOfColumns == 10); /** * Check the correctness of Square struct. @@ -1565,7 +1567,7 @@ TEST_CASE( numberOfColumns++; } - REQUIRE(numberOfColumns == 9); + REQUIRE(numberOfColumns == 10); /** * Check the correctness of CFE_ES_HousekeepingTlm_Payload_t struct. @@ -2666,7 +2668,7 @@ TEST_CASE("Test 32-bit binary.", "[main_test#10]") numberOfColumns++; } - REQUIRE(numberOfColumns == 9); + REQUIRE(numberOfColumns == 10); /** * Check the correctness of Square struct. @@ -3389,7 +3391,7 @@ TEST_CASE("Test the correctness of bit fields.", "[main_test#20]") numberOfColumns++; } - REQUIRE(numberOfColumns == 9); + REQUIRE(numberOfColumns == 10); REQUIRE(symbolRecords.at(0).at("byte_size") == std::to_string(sizeof(S))); @@ -3497,6 +3499,216 @@ TEST_CASE("Test the correctness of bit fields.", "[main_test#20]") // REQUIRE(fieldsRecords.at(1)["short_description"] == ""); // REQUIRE(fieldsRecords.at(1)["long_description"] == ""); + REQUIRE(remove("./test_db.sqlite") == 0); + delete idc; +} + +TEST_CASE("Test the correctness of namespaces.", "[main_test#21]") +{ + /** + * This assumes that the test_file was compiled on + * gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 or gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0 + * little-endian machine. + */ + + Juicer juicer; + IDataContainer* idc = 0; + Logger logger; + int rc = 0; + char* errorMessage = nullptr; + std::string little_endian = is_little_endian() ? "1" : "0"; + + logger.logWarning("This is just a test."); + std::string inputFile{TEST_FILE_5}; + + idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); + REQUIRE(idc != nullptr); + logger.logInfo("IDataContainer was constructed successfully for unit test."); + + juicer.setIDC(idc); + + rc = juicer.parse(inputFile); + + REQUIRE((juicer.getDwarfVersion() == 4 || juicer.getDwarfVersion() == 5)); + + REQUIRE(rc == JUICER_OK); + + REQUIRE(rc == JUICER_OK); + + std::string getNamespacesQuery{"SELECT * FROM namespaces;"}; + + /** + *Clean up our database handle and objects in memory. + */ + ((SQLiteDB*)(idc))->close(); + + sqlite3* database; + + rc = sqlite3_open("./test_db.sqlite", &database); + + REQUIRE(rc == SQLITE_OK); + + std::vector> namespaceRecords{}; + + rc = sqlite3_exec(database, getNamespacesQuery.c_str(), selectCallbackUsingColNameAsKey, &namespaceRecords, &errorMessage); + + REQUIRE(rc == SQLITE_OK); + REQUIRE(namespaceRecords.size() == 8); + + uint32_t numberOfColumns = 0; + + for (auto pair : namespaceRecords.at(0)) + { + numberOfColumns++; + } + + REQUIRE(numberOfColumns == 4); + + std::string getUniverse4DNamespaceQuery{"SELECT * FROM namespaces WHERE fully_qualified_name = \"Plane::_4D::Universe\";"}; + + std::vector> namespaceUniverse4DRecords{}; + + rc = sqlite3_exec(database, getUniverse4DNamespaceQuery.c_str(), selectCallbackUsingColNameAsKey, &namespaceUniverse4DRecords, &errorMessage); + + REQUIRE(rc == SQLITE_OK); + REQUIRE(namespaceUniverse4DRecords.size() == 1); + + REQUIRE(namespaceUniverse4DRecords.at(0).at("name") == "Universe"); + REQUIRE(namespaceUniverse4DRecords.at(0).at("parent") != "-1"); + + std::string getUniverse4DParentNamespaceQuery{"SELECT * FROM namespaces WHERE id = " + namespaceUniverse4DRecords.at(0).at("parent") + ";"}; + + std::vector> namespaceUniverse4DParentRecords{}; + + rc = sqlite3_exec(database, getUniverse4DParentNamespaceQuery.c_str(), selectCallbackUsingColNameAsKey, &namespaceUniverse4DParentRecords, &errorMessage); + + REQUIRE(rc == SQLITE_OK); + REQUIRE(namespaceUniverse4DParentRecords.size() == 1); + + REQUIRE(namespaceUniverse4DParentRecords.at(0).at("name") == "_4D"); + REQUIRE(namespaceUniverse4DParentRecords.at(0).at("parent") != "-1"); + REQUIRE(namespaceUniverse4DParentRecords.at(0).at("fully_qualified_name") == "Plane::_4D"); + + std::string getUniverse4DGrandparentNamespaceQuery{"SELECT * FROM namespaces WHERE id = " + namespaceUniverse4DParentRecords.at(0).at("parent") + ";"}; + + std::vector> namespaceUniverse4DGrandparentRecords{}; + + rc = sqlite3_exec(database, getUniverse4DGrandparentNamespaceQuery.c_str(), selectCallbackUsingColNameAsKey, &namespaceUniverse4DGrandparentRecords, + &errorMessage); + + REQUIRE(rc == SQLITE_OK); + REQUIRE(namespaceUniverse4DGrandparentRecords.size() == 1); + + REQUIRE(namespaceUniverse4DGrandparentRecords.at(0).at("name") == "Plane"); + REQUIRE(namespaceUniverse4DGrandparentRecords.at(0).at("parent") == "-1"); + REQUIRE(namespaceUniverse4DGrandparentRecords.at(0).at("fully_qualified_name") == "Plane"); + + // REQUIRE(namespaceRecords.at(0).at("byte_size") == std::to_string(sizeof(S))); + + /** + *Check the fields of the S struct. + */ + + // std::string sId = namespaceRecords.at(0)["id"]; + + // std::string getSFields{"SELECT * FROM fields WHERE symbol = "}; + + // getSFields += sId; + // getSFields += ";"; + + // std::vector> fieldsRecords{}; + + // rc = sqlite3_exec(database, getSFields.c_str(), selectCallbackUsingColNameAsKey, &fieldsRecords, &errorMessage); + + // REQUIRE(rc == SQLITE_OK); + + // // TODO:Incosistent across Ubuntu20 and Ubuntu22. Different compilers will have different padding schemes. + // REQUIRE(fieldsRecords.size() >= 5); + + // // Enforce order of records by offset + // std::sort(fieldsRecords.begin(), fieldsRecords.end(), [](std::map a, std::map b) + // { return std::stoi(a["byte_offset"]) < std::stoi(b["byte_offset"]); }); + + // /** + // * Ensure that we have all of the expected keys in our map; these are the column names. + // * Don't love doing this kind of thing in tests... + // */ + // for (auto record : fieldsRecords) + // { + // REQUIRE(record.find("symbol") != record.end()); + // REQUIRE(record.find("name") != record.end()); + // REQUIRE(record.find("byte_offset") != record.end()); + // REQUIRE(record.find("type") != record.end()); + + // REQUIRE(record.find("little_endian") != record.end()); + // REQUIRE(record.find("bit_size") != record.end()); + // REQUIRE(record.find("bit_offset") != record.end()); + // REQUIRE(record.find("short_description") != record.end()); + // REQUIRE(record.find("long_description") != record.end()); + // } + + // REQUIRE(fieldsRecords.at(0)["name"] == "before"); + /** + *Check the correctness of the fields + */ + + // std::string getBeforeType{"SELECT * FROM symbols where id="}; + + // getBeforeType += fieldsRecords.at(0)["type"]; + // getBeforeType += ";"; + + // std::vector> beforeSymbolRecords{}; + + // rc = sqlite3_exec(database, getBeforeType.c_str(), selectCallbackUsingColNameAsKey, &beforeSymbolRecords, &errorMessage); + + // REQUIRE(rc == SQLITE_OK); + + // REQUIRE(beforeSymbolRecords.size() == 1); + + // std::string beforeType{beforeSymbolRecords.at(0).at("id")}; + + // REQUIRE(fieldsRecords.at(0)["symbol"] == symbolRecords.at(0)["id"]); + // REQUIRE(fieldsRecords.at(0)["name"] == "before"); + // REQUIRE(fieldsRecords.at(0)["byte_offset"] == std::to_string(offsetof(S, before))); + // REQUIRE(fieldsRecords.at(0)["type"] == beforeType); + // REQUIRE(fieldsRecords.at(0)["little_endian"] == little_endian); + // REQUIRE(fieldsRecords.at(0)["bit_size"] == "0"); + // REQUIRE(fieldsRecords.at(0)["bit_offset"] == "0"); + // REQUIRE(fieldsRecords.at(0)["short_description"] == ""); + // REQUIRE(fieldsRecords.at(0)["long_description"] == ""); + + // TODO:Inconsistent across Ubuntu20 and Ubuntu22. Different compilers will have different padding schemes. + + // REQUIRE(fieldsRecords.at(1)["name"] == "j"); + // /** + // *Check the correctness of the fields + // */ + + // std::string getFieldType{"SELECT * FROM symbols where id="}; + + // getFieldType += fieldsRecords.at(1)["type"]; + // getFieldType += ";"; + + // std::vector> fieldSymbolRecords{}; + + // rc = sqlite3_exec(database, getFieldType.c_str(), selectCallbackUsingColNameAsKey, &fieldSymbolRecords, &errorMessage); + + // REQUIRE(rc == SQLITE_OK); + + // REQUIRE(fieldSymbolRecords.size() == 1); + + // std::string fieldType{fieldSymbolRecords.at(0).at("id")}; + + // REQUIRE(fieldsRecords.at(1)["symbol"] == symbolRecords.at(0)["id"]); + // REQUIRE(fieldsRecords.at(1)["name"] == "j"); + // // REQUIRE(fieldsRecords.at(1)["byte_offset"] == std::to_string(offsetof(S, j))); + // REQUIRE(fieldsRecords.at(1)["type"] == fieldType); + // REQUIRE(fieldsRecords.at(1)["little_endian"] == little_endian); + // REQUIRE(fieldsRecords.at(1)["bit_size"] == "5"); + // REQUIRE(fieldsRecords.at(1)["bit_offset"] == "19"); + // REQUIRE(fieldsRecords.at(1)["short_description"] == ""); + // REQUIRE(fieldsRecords.at(1)["long_description"] == ""); + REQUIRE(remove("./test_db.sqlite") == 0); delete idc; } \ No newline at end of file diff --git a/unit-test/namespaces_test.cpp b/unit-test/namespaces_test.cpp index 125ec391..4aee78d9 100644 --- a/unit-test/namespaces_test.cpp +++ b/unit-test/namespaces_test.cpp @@ -1,3 +1,23 @@ +#include "stdint.h" +/** + *The fields padding1 and padding2(as the name implies) are to prevent + *gcc from inserting padding at compile-time and altering the expected results in our tests. + * Tested on Ubuntu 20.04 and Ubuntu 18.04. + */ +typedef struct +{ + int32_t width = 101; + uint16_t stuff; + uint16_t padding1; + int32_t length; + uint16_t more_stuff; + uint16_t padding2; + float floating_stuff; + float matrix3D[2][4][4]; + float matrix1D[2]; + uint8_t extra; +} Square; + namespace Universe { namespace Earth @@ -31,8 +51,27 @@ struct Shape }; } // namespace _3D +namespace _2D +{ +typedef struct +{ + int32_t width = 101; + uint16_t stuff; + uint16_t padding1; + int32_t length; + uint16_t more_stuff; + uint16_t padding2; + float floating_stuff; + float matrix3D[2][4][4]; + float matrix1D[2]; + uint8_t extra; +} Square; +} // namespace _2D + namespace _4D { + +Square s3[6]; namespace Universe { struct Shape @@ -45,8 +84,12 @@ struct Shape } // namespace Plane Universe::Earth::Shape earth{}; -// Universe::Mars::Shape mars{}; +Universe::Mars::Shape mars{}; -// Plane::_3D::Shape Space{}; +Plane::_3D::Shape Space{}; Plane::_4D::Universe::Shape Star{}; + +Square s{}; + +Plane::_2D::Square s2{}; \ No newline at end of file