diff --git a/.cproject b/.cproject index c683b296..8de35ed8 100644 --- a/.cproject +++ b/.cproject @@ -1,9 +1,11 @@ - - - + + + + + @@ -14,115 +16,35 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -132,32 +54,28 @@ - + - - - - - - - - - - + + + + + + \ No newline at end of file diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b0c06c54..7364db3e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -12,27 +12,35 @@ jobs: runs-on: ${{matrix.os}} strategy: matrix: - os: [ubuntu-18.04, ubuntu-latest] + os: [ubuntu-latest] steps: - uses: actions/checkout@v2 - - name: Install Python 3 - uses: actions/setup-python@v1 with: - python-version: 3.6 - - name: Install dependencies - run: | - pip install cpp-coveralls==0.4.2 - sudo apt-get install libdwarf-dev - sudo apt-get install libelf-dev - sudo apt-get install libsqlite3-dev - sudo apt-get install g++ - sudo apt-get install gcovr - - name: Checkout submodules - run: git submodule update --init --recursive - - name: Run tests - run: make coverage - #- name: publish to coveralls.io - #uses: coverallsapp/github-action@v1.1.2 - #with: - # github-token: ${{ github.token }} + submodules: true # Clone submodules + fetch-depth: 0 # Ensure full repository history is fetched + + # Set up Docker Buildx (optional, useful for multi-platform builds) + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + # Build the Docker image + # - name: Build Docker image + # uses: docker/build-push-action@v5 + # with: + # context: . + # push: false # Do not push the image + # tags: juicer:latest # Local tag for the built image + + - name: Build Docker image For Ubuntu22 + run: docker build --no-cache -t juicer:latest -f Dockerfile.ubuntu22 . + + - name: Build Docker image For Ubuntu20 + run: docker build --no-cache -t juicer:latest -f Dockerfile.ubuntu20 . + - name: Copy coverage report to host + run: docker image ls && img_id=$(docker create juicer:latest) && docker cp $img_id:/home/docker/juicer/coverage.gcov . + - name: publish to coveralls.io + run: wget https://github.com/coverallsapp/coverage-reporter/releases/download/v0.6.14/coveralls-linux && chmod a+x ./coveralls-linux && COVERALLS_REPO_TOKEN=${{ secrets.COVERALLS_REPO_TOKEN }} ./coveralls-linux + + - name: Build Docker image For Ubuntu18 + run: docker build --no-cache -t juicer:latest -f Dockerfile.ubuntu18 . diff --git a/.gitignore b/.gitignore index 378eac25..b201b2d4 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ build +*autosave diff --git a/.gitmodules b/.gitmodules index c4f0301e..7dafbf5c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "Catch2"] path = Catch2 - url = git@penguin.windhoverlabs.lan:airliner/catch2.git + url = git@github.com:WindhoverLabs/Catch2.git diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml index d7da895f..8f3bb82c 100644 --- a/.settings/language.settings.xml +++ b/.settings/language.settings.xml @@ -1,35 +1,11 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs new file mode 100644 index 00000000..c8ec5df2 --- /dev/null +++ b/.settings/org.eclipse.cdt.core.prefs @@ -0,0 +1,6 @@ +doxygen/doxygen_new_line_after_brief=true +doxygen/doxygen_use_brief_tag=false +doxygen/doxygen_use_javadoc_tags=true +doxygen/doxygen_use_pre_tag=false +doxygen/doxygen_use_structural_commands=false +eclipse.preferences.version=1 diff --git a/Catch2 b/Catch2 index 7f21cc6c..182c910b 160000 --- a/Catch2 +++ b/Catch2 @@ -1 +1 @@ -Subproject commit 7f21cc6c5599f59835f769debf13b4c3e6148a28 +Subproject commit 182c910b4b63ff587a3440e08f84f70497e49a81 diff --git a/Dockerfile b/Dockerfile.ubuntu18 similarity index 67% rename from Dockerfile rename to Dockerfile.ubuntu18 index 8b048040..3c7a41b5 100644 --- a/Dockerfile +++ b/Dockerfile.ubuntu18 @@ -1,4 +1,4 @@ -FROM ubuntu:20.04 +FROM ubuntu:18.04 RUN apt update ARG DEBIAN_FRONTEND=noninteractive ENV TERM xterm-256color @@ -13,12 +13,18 @@ RUN apt-get install -y libelf-dev RUN apt-get install -y libsqlite3-dev RUN apt-get install -y libssl-dev RUN apt-get install -y doxygen +RUN apt-get install -y gcovr RUN mkdir /home/docker COPY . /home/docker/juicer + + +RUN cd /home/docker/juicer && make clean +RUN cd /home/docker/juicer && make docs + RUN cd /home/docker/juicer && make RUN cd /home/docker/juicer && make clean -RUN cd /home/docker/juicer && make build-tests +RUN cd /home/docker/juicer && make all WORKDIR /home/docker/juicer/build RUN ./juicer-ut "[Enumeration]" RUN ./juicer-ut "[main_test#1]" @@ -29,11 +35,21 @@ RUN ./juicer-ut "[main_test#5]" RUN ./juicer-ut "[main_test#6]" RUN ./juicer-ut "[main_test#7]" RUN ./juicer-ut "[main_test#8]" +RUN ./juicer-ut "[main_test#9]" +RUN ./juicer-ut "[main_test#10]" +RUN ./juicer-ut "[main_test#11]" +RUN ./juicer-ut "[main_test#12]" +RUN ./juicer-ut "[main_test#13]" +RUN ./juicer-ut "[main_test#14]" +RUN ./juicer-ut "[main_test#15]" +RUN ./juicer-ut "[main_test#16]" +RUN ./juicer-ut "[main_test#17]" +RUN ./juicer-ut "[main_test#18]" +RUN ./juicer-ut "[main_test#19]" +RUN ./juicer-ut "[main_test#20]" RUN ./juicer-ut "[Module]" RUN ./juicer-ut "[Symbol]" -RUN cd /home/docker/juicer && make clean -RUN cd /home/docker/juicer && make docs diff --git a/Dockerfile.ubuntu18.dev b/Dockerfile.ubuntu18.dev new file mode 100644 index 00000000..bc3295d9 --- /dev/null +++ b/Dockerfile.ubuntu18.dev @@ -0,0 +1,22 @@ +FROM ubuntu:18.04 +RUN apt update +ARG DEBIAN_FRONTEND=noninteractive +ENV TERM xterm-256color +RUN apt-get update && \ + apt-get -y install sudo + +RUN apt-get install -y gcc-multilib +RUN apt-get install -y g++-multilib +RUN apt-get install -y libdwarf-dev +RUN apt-get install -y make +RUN apt-get install -y libelf-dev +RUN apt-get install -y libsqlite3-dev +RUN apt-get install -y libssl-dev +RUN apt-get install -y doxygen +RUN apt-get install -y gcovr + +RUN mkdir /home/docker +RUN mkdir /home/docker/juicer +WORKDIR /home/docker/juicer + + diff --git a/Dockerfile.ubuntu20 b/Dockerfile.ubuntu20 new file mode 100644 index 00000000..3cd7b29d --- /dev/null +++ b/Dockerfile.ubuntu20 @@ -0,0 +1,71 @@ +FROM ubuntu:20.04 +RUN apt update +ARG DEBIAN_FRONTEND=noninteractive +ENV TERM xterm-256color +RUN apt-get update && \ + apt-get -y install sudo + +RUN apt-get install -y gcc-multilib +RUN apt-get install -y g++-multilib +RUN apt-get install -y libdwarf-dev +RUN apt-get install -y make +RUN apt-get install -y libelf-dev +RUN apt-get install -y libsqlite3-dev +RUN apt-get install -y libssl-dev +RUN apt-get install -y doxygen +RUN apt-get install -y gcovr + + + +RUN apt-get install -y gnupg2 +RUN apt-get install -y software-properties-common +RUN apt-get install -y python3-pip +RUN pip3 install PyYAML + +RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 15CF4D18AF4F7421 +RUN add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal main' +RUN apt-get install -y clang-format + +RUN mkdir /home/docker +COPY . /home/docker/juicer + + +RUN cd /home/docker/juicer && make check-format + +RUN cd /home/docker/juicer && make clean +RUN cd /home/docker/juicer && make docs + +RUN cd /home/docker/juicer && make +RUN cd /home/docker/juicer && make clean +RUN cd /home/docker/juicer && make all +WORKDIR /home/docker/juicer/build +RUN ./juicer-ut "[Enumeration]" +RUN ./juicer-ut "[main_test#1]" +RUN ./juicer-ut "[main_test#2]" +RUN ./juicer-ut "[main_test#3]" +RUN ./juicer-ut "[main_test#4]" +RUN ./juicer-ut "[main_test#5]" +RUN ./juicer-ut "[main_test#6]" +RUN ./juicer-ut "[main_test#7]" +RUN ./juicer-ut "[main_test#8]" +RUN ./juicer-ut "[main_test#9]" +RUN ./juicer-ut "[main_test#10]" +RUN ./juicer-ut "[main_test#11]" +RUN ./juicer-ut "[main_test#12]" +RUN ./juicer-ut "[main_test#13]" +RUN ./juicer-ut "[main_test#14]" +RUN ./juicer-ut "[main_test#15]" +RUN ./juicer-ut "[main_test#16]" +RUN ./juicer-ut "[main_test#17]" +RUN ./juicer-ut "[main_test#18]" +RUN ./juicer-ut "[main_test#19]" +RUN ./juicer-ut "[main_test#20]" +RUN ./juicer-ut "[Module]" +RUN ./juicer-ut "[Symbol]" + +RUN cd /home/docker/juicer && make coverage +#Useful for CI +RUN cd /home/docker/juicer && gcovr --filter /home/docker/juicer/src/ --object-directory /home/docker/juicer/build/ut_obj/ --xml coverage.gcov + + + diff --git a/Dockerfile.ubuntu20.dev b/Dockerfile.ubuntu20.dev new file mode 100644 index 00000000..61f55e19 --- /dev/null +++ b/Dockerfile.ubuntu20.dev @@ -0,0 +1,29 @@ +FROM ubuntu:20.04 +RUN apt update +ARG DEBIAN_FRONTEND=noninteractive +ENV TERM xterm-256color +RUN apt-get update && \ + apt-get -y install sudo + +RUN apt-get install -y gcc-multilib +RUN apt-get install -y g++-multilib +RUN apt-get install -y libdwarf-dev +RUN apt-get install -y make +RUN apt-get install -y libelf-dev +RUN apt-get install -y libsqlite3-dev +RUN apt-get install -y libssl-dev +RUN apt-get install -y doxygen +RUN apt-get install -y gdb +RUN apt-get install -y gcovr +RUN apt-get install -y gnupg2 +RUN apt-get install -y software-properties-common +RUN apt-get install -y python3-pip +RUN pip3 install PyYAML + +RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 15CF4D18AF4F7421 +RUN add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal main' +RUN apt-get install -y clang-format + +RUN mkdir /home/docker +RUN mkdir /home/docker/juicer +WORKDIR /home/docker/juicer diff --git a/Dockerfile.ubuntu22 b/Dockerfile.ubuntu22 new file mode 100644 index 00000000..1ae43458 --- /dev/null +++ b/Dockerfile.ubuntu22 @@ -0,0 +1,58 @@ +FROM ubuntu:22.04 +RUN apt update +ARG DEBIAN_FRONTEND=noninteractive +ENV TERM xterm-256color +RUN apt-get update && \ + apt-get -y install sudo + +RUN apt-get install -y gcc-multilib +RUN apt-get install -y g++-multilib +RUN apt-get install -y libdwarf-dev +RUN apt-get install -y make +RUN apt-get install -y libelf-dev +RUN apt-get install -y libsqlite3-dev +RUN apt-get install -y libssl-dev +RUN apt-get install -y doxygen +RUN apt-get install -y gcovr + +RUN mkdir /home/docker +COPY . /home/docker/juicer + + +RUN cd /home/docker/juicer && make clean +RUN cd /home/docker/juicer && make docs + +RUN cd /home/docker/juicer && make +RUN cd /home/docker/juicer && make clean +RUN cd /home/docker/juicer && make all +WORKDIR /home/docker/juicer/build +RUN ./juicer-ut "[Enumeration]" +RUN ./juicer-ut "[main_test#1]" +RUN ./juicer-ut "[main_test#2]" +RUN ./juicer-ut "[main_test#3]" +RUN ./juicer-ut "[main_test#4]" +RUN ./juicer-ut "[main_test#5]" +RUN ./juicer-ut "[main_test#6]" +RUN ./juicer-ut "[main_test#7]" +RUN ./juicer-ut "[main_test#8]" +RUN ./juicer-ut "[main_test#9]" +RUN ./juicer-ut "[main_test#10]" +RUN ./juicer-ut "[main_test#11]" +RUN ./juicer-ut "[main_test#12]" +RUN ./juicer-ut "[main_test#13]" +RUN ./juicer-ut "[main_test#14]" +RUN ./juicer-ut "[main_test#15]" +RUN ./juicer-ut "[main_test#16]" +RUN ./juicer-ut "[main_test#17]" +RUN ./juicer-ut "[main_test#18]" +RUN ./juicer-ut "[main_test#19]" +RUN ./juicer-ut "[main_test#20]" +RUN ./juicer-ut "[Module]" +RUN ./juicer-ut "[Symbol]" + +RUN cd /home/docker/juicer && make coverage +#Useful for CI +RUN cd /home/docker/juicer && gcovr --filter /home/docker/juicer/src/ --object-directory /home/docker/juicer/build/ut_obj/ --xml coverage.gcov + + + diff --git a/Dockerfile.ubuntu22.dev b/Dockerfile.ubuntu22.dev new file mode 100644 index 00000000..79f5f591 --- /dev/null +++ b/Dockerfile.ubuntu22.dev @@ -0,0 +1,21 @@ +FROM ubuntu:22.04 +RUN apt update +ARG DEBIAN_FRONTEND=noninteractive +ENV TERM xterm-256color +RUN apt-get update && \ + apt-get -y install sudo + +RUN apt-get install -y gcc-multilib +RUN apt-get install -y g++-multilib +RUN apt-get install -y libdwarf-dev +RUN apt-get install -y make +RUN apt-get install -y libelf-dev +RUN apt-get install -y libsqlite3-dev +RUN apt-get install -y libssl-dev +RUN apt-get install -y doxygen +RUN apt-get install -y gdb +RUN apt-get install -y gcovr + +RUN mkdir /home/docker +RUN mkdir /home/docker/juicer +WORKDIR /home/docker/juicer diff --git a/Images/bit_packed_struct.png b/Images/bit_packed_struct.png new file mode 100644 index 00000000..abe8e1a2 Binary files /dev/null and b/Images/bit_packed_struct.png differ diff --git a/Images/fields_table.png b/Images/fields_table.png index 1c5b693c..2475b83e 100644 Binary files a/Images/fields_table.png and b/Images/fields_table.png differ diff --git a/Images/symbols_table.png b/Images/symbols_table.png index fd679908..6f038c88 100644 Binary files a/Images/symbols_table.png and b/Images/symbols_table.png differ diff --git a/Makefile b/Makefile index 81d1d406..f9213f60 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ CATCH2_DIR := $(ROOT_DIR)/Catch2 # Unit test directories UT_SRC_DIR := $(ROOT_DIR)/unit-test UT_OBJ_DIR := $(BUILD_DIR)/ut_obj +UT_OBJ_32BIT_DIR := $(BUILD_DIR)/ut_obj_32 UT_BIN_DIR := $(BUILD_DIR) UT_INCLUDES := -I$(CATCH2_DIR)/single_include/catch2 @@ -25,28 +26,38 @@ SRC := $(wildcard $(SRC_DIR)/*.cpp) OBJ := $(SRC:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o) # Unit test files -UT_EXE := $(UT_BIN_DIR)/juicer-ut -UT_SRC := $(wildcard $(UT_SRC_DIR)/*.cpp) $(filter-out $(SRC_DIR)/main.cpp, $(SRC)) -UT_OBJ := $(UT_SRC:$(UT_SRC_DIR)/%.cpp=$(UT_OBJ_DIR)/%.o) -UT_OBJ := $(UT_OBJ:$(SRC_DIR)/%.cpp=$(UT_OBJ_DIR)/%.o) +UT_EXE := $(UT_BIN_DIR)/juicer-ut + +UT_EXE_32BIT := $(UT_BIN_DIR)/juicer-ut-32 +UT_SRC := $(wildcard $(UT_SRC_DIR)/*.cpp) $(filter-out $(SRC_DIR)/main.cpp, $(SRC)) +UT_OBJ := $(UT_SRC:$(UT_SRC_DIR)/%.cpp=$(UT_OBJ_DIR)/%.o) +UT_OBJ := $(UT_OBJ:$(SRC_DIR)/%.cpp=$(UT_OBJ_DIR)/%.o) + + +UT_SRC_32 := $(wildcard $(UT_SRC_DIR)/test_file*.cpp) +UT_OBJ_32 := $(UT_SRC_32:$(UT_SRC_DIR)/test_file%.cpp=$(UT_OBJ_32BIT_DIR)/test_file%.o) +UT_OBJ_32 := $(UT_OBJ_32:$(UT_SRC_DIR)/test_file%.cpp=$(UT_OBJ_32BIT_DIR)/test_file%.o) + # Set target flags -CPPFLAGS := -MMD -MP -std=c++14 -fmessage-length=0 $(INCLUDES) -CFLAGS := -Wall -g -LDFLAGS := -Llib -LDLIBS := -lm -ldwarf -lsqlite3 -lelf -lcrypto +CPPFLAGS := -MMD -MP -std=c++14 -fmessage-length=0 $(INCLUDES) +CFLAGS := -Wall -g3 +CFLAGS_32BIT := -Wall -g3 -m32 +LDFLAGS := -Llib +LDLIBS := -lm -ldwarf -lsqlite3 -lelf -lcrypto # Set unit test flags -UT_CPPFLAGS := $(CPPFLAGS) $(UT_INCLUDES) -UT_CFLAGS := $(CFLAGS) --coverage -UT_LDFLAGS := $(LDFLAGS) -UT_LDLIBS := $(LDLIBS) -lgcov +UT_CPPFLAGS := $(CPPFLAGS) $(UT_INCLUDES) +UT_CFLAGS := $(CFLAGS) --coverage +UT_CFLAGS_32BIT := $(CFLAGS_32BIT) --coverage +UT_LDFLAGS := $(LDFLAGS) +UT_LDLIBS := $(LDLIBS) -lgcov # Set tools CC := g++ LD := g++ -.PHONY: all clean run-tests coverage +.PHONY: all clean run-tests coverage docs # Target recipes $(EXE): $(OBJ) @@ -62,17 +73,38 @@ $(OBJ_DIR): $(UT_EXE): $(UT_OBJ) $(LD) $(UT_LDFLAGS) $^ $(UT_LDLIBS) -o $@ + + +$(UT_EXE_32BIT): $(UT_OBJ_32) + + $(UT_OBJ_DIR)/%.o: $(UT_SRC_DIR)/%.cpp | $(UT_OBJ_DIR) $(CC) $(UT_CPPFLAGS) $(UT_CFLAGS) -c $< -o $@ + +$(UT_OBJ_DIR)/%.o: $(UT_SRC_DIR)/%.cpp | $(UT_OBJ_DIR) + $(CC) $(UT_CPPFLAGS) $(UT_CFLAGS) -c $< -o $@ + + + $(UT_OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp | $(UT_OBJ_DIR) $(CC) $(UT_CPPFLAGS) $(UT_CFLAGS) -c $< -o $@ -$(UT_OBJ_DIR): +$(UT_OBJ_32BIT_DIR)/test_file%.o: $(UT_SRC_DIR)/test_file%.cpp | $(UT_OBJ_32BIT_DIR) + $(CC) $(UT_CPPFLAGS) $(UT_CFLAGS_32BIT) -c $< -o $@ + + +$(UT_OBJ_DIR): mkdir -p $@ -run-tests: | $(UT_EXE) + +$(UT_OBJ_32BIT_DIR): + mkdir -p $@ + + +run-tests: $(UT_EXE_32BIT) | $(UT_EXE) -(cd $(BUILD_DIR); $(UT_EXE)) + build-tests: | $(UT_EXE) @@ -82,7 +114,8 @@ $(COVERAGE_DIR)/index.html: | run-tests mkdir -p $(COVERAGE_DIR) (cd $(COVERAGE_DIR); gcovr $(ROOT_DIR) --root $(ROOT_DIR) --object-directory $(UT_OBJ_DIR) --filter $(ROOT_DIR)/src/ --html --html-details -o index.html) -all: $(EXE) $(UT_EXE) + +all: $(EXE) $(UT_EXE) $(UT_EXE_32BIT) clean: @$(RM) -Rf $(BUILD_DIR) @@ -91,9 +124,29 @@ clean: -include $(OBJ:.o=.d) -docker-build: - @sudo docker build --no-cache -t juicer:latest -f Dockerfile . +docker-ubuntu18-build: + @sudo docker build --no-cache -t juicer:ubuntu18 -f Dockerfile.ubuntu18 . + + +docker-ubuntu22-build: + @sudo docker build --no-cache -t juicer:ubuntu22 -f Dockerfile.ubuntu22 . + +docker-ubuntu20-build: + @sudo docker build --no-cache -t juicer:ubuntu20 -f Dockerfile.ubuntu20 . + + +docker-ubuntu22-build-dev: + @sudo docker build --no-cache -t juicer-dev:ubuntu22 -f Dockerfile.ubuntu22.dev . + @sudo docker run -v .:/home/docker/juicer -it juicer-dev:ubuntu22 bash + + +docker-ubuntu20-build-dev: + @sudo docker build --no-cache -t juicer-dev:ubuntu20 -f Dockerfile.ubuntu20.dev . + @sudo docker run -v .:/home/docker/juicer -it juicer-dev:ubuntu20 bash +docker-ubuntu18-build-dev: + @sudo docker build --no-cache -t juicer-dev:ubuntu18 -f Dockerfile.ubuntu18 . + @sudo docker run -v .:/home/docker/juicer -it juicer-dev:ubuntu18 bash check-format: @python3 clang_format_all.py --config clang_format_all_config.yaml diff --git a/README.md b/README.md index 5fc59bdf..c4760666 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ [![Run juicer tests](https://github.com/WindhoverLabs/juicer/actions/workflows/ci.yaml/badge.svg)](https://github.com/WindhoverLabs/juicer/actions/workflows/ci.yaml) +[![Coverage Status](https://coveralls.io/repos/github/WindhoverLabs/juicer/badge.svg?branch=unit_test_updates)](https://coveralls.io/github/WindhoverLabs/juicer?branch=unit_test_updates) # Table of Contents 1. [Dependencies](#dependencies) @@ -10,7 +11,12 @@ 6. [Environment Setup](#environment-setup) 7. [Testing](#testing) 8. [DWARF Support](#dwarf_support) -9. [vxWorks Support](#vxWorks) +9. [Notes on Macros](#notes_on_macros) +10. [Extra Elf Features](#extra_elf_features) +11. [vxWorks Support](#vxWorks) +12. [Notes On Multiple DWARF Versions](#multiple_dwarf_versions) +13. [Bitfields](#Bitfields) +14. [Docker Dev Environments](#docker_dev_env) ## Dependencies * `libdwarf-dev` @@ -60,13 +66,15 @@ make run-tests ## What is it? -juicer extracts structs, arrays, enumerations and intrinsic types(support for everything else is planned for the future, but it is not a priority at the moment) from executable elf files and stores them in a SQLite database. +juicer extracts structs, arrays, enumerations, macros and intrinsic types(support for everything else is planned for the future, but it is not a priority at the moment) from executable elf files and stores them in a SQLite database. ### An Example Imagine we wrote some elf_file.cpp that looks like this. ``` #include "stdint.h" +#define ARRAY_1D_SIZE 2 + typedef struct { int32_t width = 101; @@ -76,8 +84,8 @@ typedef struct uint16_t more_stuff; uint16_t padding2; float floating_stuff; - float matrix3D[2][4][4]; - float matrix1D[2]; + float matrix3D[ARRAY_1D_SIZE][4][4]; + float matrix1D[ARRAY_1D_SIZE]; }Square; Square sq = {}; @@ -89,6 +97,15 @@ Square sq = {}; g++ -std=c++14 elf_file.cpp -g -c -o elf_file ``` +To include macros in the output, make sure to pass "-g3" when compiling: + + +``` +g++ -std=c++14 elf_file.cpp -g -g3 -c -o elf_file +``` +NOTE:Please beware that compiler switchess may have different names for different compilers. +Here we use gcc as an example since it is a compiler that is accessible to most teams. + Assuming you've built juicer successfully, you can give this binary file to juicer: ``` @@ -100,20 +117,18 @@ This tells juicer to squeeze and extract as much as possible out of the binary a After juicer is done, you will find a database populated with data about our binary file at `build/new_db.sqlite`. The database should have the following schemas: +"*" = PRIMARY KEY +"+" = FOREIGN KEY + ### elfs -| id* | name | checksum | date | little_endian | -| --- | --- | --- | --- | --- | -|INTEGER | TEXT | INTEGER | DATETIME | BOOLEAN | +| id* | name | md5 | date | little_endian | short_description | long_description | +| --- | --- |---------| --- | --- | -- | -- | +|INTEGER | TEXT | INTEGER | DATETIME | BOOLEAN | TEXT | TEXT | ### enumerations -| symbol* | value* | name | -| --- | --- | --- | -| INTEGER | INTEGER | TEXT | - -### bit_fields -|field* | bit_size | bit_offset | -|---|---|---| -| INTEGER | INTEGER | INTEGER | +| symbol* | value* | name | short_description | long_description | +| --- | --- | --- | -- | -- | +| INTEGER | INTEGER | TEXT | TEXT | TEXT | ### fields | id* | name | symbol+ | byte_offset | type+ | little_endian | bit_size | bit_offset | @@ -126,9 +141,9 @@ After juicer is done, you will find a database populated with data about our bin | INTEGER | INTEGER | TEXT | INTEGER ### symbols -| id* | elf+ | name | byte_size | -| ---| --- | --- | --- | -| INTEGER | INTEGER | TEXT | INTEGER | +| id* | elf+ | name | byte_size | artifact* | target_symbol* | encoding* | short_description | long_descriptions | +| ---| --- | --- | --- |-----------|----------------|-----------|------|------| +| INTEGER | INTEGER | TEXT | INTEGER | INTEGER | INTEGER | INTEGER | TEXT | TEXT | In our specific example, the **symbols** and **fields** tables are the ones we are interested in. @@ -161,13 +176,13 @@ This is how juicer stores data in the database. # GCC Compatibility Since`juicer` is reading ELF files, the compiler one uses or the specific linux version *can* affect the behavior of the libelf libraries. -Because of this we have tested `juicer`on the specified platforms in the table below. +Because of this we have tested `juicer` (and continuously test in CI)on the specified platforms in the table below. -| Ubuntu Version| GCC Version(s) | -|---|---| -| `Ubuntu 16.04.7 LTS` | `gcc 5.4.0`, ` gcc 6.5.0 ` | -| `Ubuntu 18.04.5 LTS` | ` gcc 7.5.0`, `gcc 8.4.0` | -| `Ubuntu 20.04.1 LTS` | `gcc 7.5.0`, `gcc 8.4.0`, `gcc 9.3.0` | +| Ubuntu Version | GCC Version(s) | DWARF Version | +|---|---| ---| +| `Ubuntu 18.04.1 LTS` | `7.5.0` | 4 | +| `Ubuntu 20.04.1 LTS` | `9.4.0` | 4 | +| `Ubuntu 22.04.5 LTS` | `11.4.0` | 5 | # Padding @@ -290,26 +305,29 @@ make coverage This will run all unit tests on juicer and generate a test coverage report for you. After `make` is done, the test coverage report can be found on `build/coverage/index.html`. ## Dwarf Support -At the moment `juicer` follows the DWARF4 specification, which is the standard in all versions of gcc at the moment. If this changes, then this document will be updated accordingly. +At the moment `juicer` follows the DWARF4 and DWARF5 specifications. If this changes, then this document will be updated accordingly. As juicer evolves, dwarf support will grow and evolve as well. At the moment, we don't adhere to a particular DWARF version as we add support to the things that we need for our code base, which is airliner. In other words, we *mostly* support `C` code, or `C++` code without any cutting edge/modern features. For example, modern features such as `templates` or `namespaces` are not supported. If juicer finds these things in your elf files, it will simply ignore them. To have a more concrete idea of what we *do* support in the DWARF, take a look at the table below which records all DWARF tags we support. ### Dwarf Tags -| Name | Description | -| ---| --- | -| DW_TAG_base_type | This is the tag that represents intrinsic types such as `int` and `char`. | -| DW_TAG_typedef | This is the tag that represents anything that is typdef'd in code such as `typedef struct{...}`. At the moment, types such as `typedef int16 my_int` do *not* work. We will investigate this issue in the future, however, it is not a priority at the moment.| +| Name | Description | +|-----------------------| --- | +| DW_TAG_base_type | This is the tag that represents intrinsic types such as `int` and `char`. | +| DW_TAG_typedef | This is the tag that represents anything that is typdef'd in code such as `typedef struct{...}` `typedef int16 my_int`. This is what the "target_symbol" column is for in the symbols table. | | DW_TAG_structure_type | This is the tag that represents structs such as `struct Square{ int width; int length; };` | -| DW_TAG_array_type | This is the tag that represents *statically* allocated arrays such as `int flat_array[] = {1,2,3,4,5,6};`. Noe that this does not include dynamic arrays such as those allocated by malloc or new calls.| -| DW_TAG_pointer_type | This is the tag that represents pointers in code such as `int* ptr = nullptr`| +| DW_TAG_array_type | This is the tag that represents *statically* allocated arrays such as `int flat_array[] = {1,2,3,4,5,6};`. Note that this does not include dynamic arrays such as those allocated by malloc or new calls.| +| DW_TAG_pointer_type | This is the tag that represents pointers in code such as `int* ptr = nullptr`| | DW_TAG_enumeration_type | This is the tag that represents enumerations such as `enum Color{RED,BLUE,YELLOW};` | -| DW_TAG_const_type | This is the tag that represents C/C++ const qualified type such as `sizetype`, which is used by containers(like std::vector) in the STL C++ library. | +| DW_TAG_const_type | This is the tag that represents C/C++ const qualified type such as `sizetype`, which is used by containers(like std::vector) in the STL C++ library. | +| DW_MACRO_define | This tag represents define macros such as "#define CFE_MISSION_ES_PERF_MAX_IDS 128"| +| DW_AT_decl_file | This tag represents the file where a certain symbol is declared. Very useful for traceability of source code.| +| DW_AT_encoding | The encoding of base type. For example; "unsigned int" will have encoding "DW_ATE_unsigned". This is what the "encodings" table is for in the SQLITE db.| For more details on the DWARF debugging format, go on [here](http://www.dwarfstd.org/doc/DWARF4.pdf). ### `void*` -DWARF version 4 has this to say about void pointers: +DWARF version 4 and 5 has this to say about void pointers: > The interpretation of this debugging information entry is intentionally left flexible to allow it to be interpreted appropriately in different languages. For example, in C and C++ the language @@ -321,6 +339,50 @@ referenced by the type attribute of pointer types and typedef declarations for ' juicer behaves accordingly. If a pointer does not have a type(meaning it does not have a DW_AT_type attribute), then it is assumed that the pointer in question is of the `void*` type. +## Notes On #define Macros +During testing we found that some pattern causes the macro being defined to "disappear" from the DWARF section: + +When this happens, it is most likely a case of the macro being on a seperate group number inside of the DWARF. + +To ensure juicer queries all macros, users can pass the "group number" via the "-g" flag. + +For example the command: +``` +./juicer -g 5 --input elf_file --mode SQLITE --output build/new_db.sqlite -v4 +``` + +tells juicer to get macros from group "5". The default is group "0", which is enough for most cases. + +This seems to happen on unlinked compiled ELF files that have the following define pattern where there is an #include between #define(s): +```C +#define MAC1 2 +#define MAC2 3 +#include "macro_test.h" +#define MAC3 4 +``` + +This is rare(especially unlinked files), but it does happen. In any case "-g" flag can be used to query macros (or any other DWARF data) +from as many groups(starting at 0) as the the ELF file has. + +For more details on this issue and other macro issues:https://github.com/WindhoverLabs/juicer/issues/35 + + +## Extra ELF Features + +jucier's main focus is to extract DWARF, however, it can extract ELF sections too. To extract elf sections pass the extras "-x" flag: + +``` +./juicer -x --input elf_file --mode SQLITE --output build/new_db.sqlite -v4 +``` + +This can be useful for extracting data from object files such as static variables that are assigned at build time and whose +contents are stored in the elf symbols table. For an example of this see the "query_symbols.py" script under this repo. + +To learn more about the different ELF sections and how they're structured, there is a copy of the ELF standard under the docs directory on the repo. + + + + ## VxWorks Support At the moment vxWorks support is a work in progress. Support is currently *not* tested, so at the moment it is on its own [branch] (https://github.com/WindhoverLabs/juicer/tree/vxWorks). @@ -331,6 +393,45 @@ At the moment vxWorks support is a work in progress. Support is currently *not* ``` catchsegv ./juicer-ut "[main_test#3]" addr2line -e ./juicer-ut 0x19646c + +``` + + +## Notes On Multiple DWARF Versions +- At the time of writing, juicer has been tested on DWARF4 and DWARF5. +- Do *not* use DWARF experimental support from your compiler. Use the *default* DWARF version, whether that is 5 or 4. When using a +DWARF version that still is experimental for your compiler, it is not guaranteed juicer will parse the binary correctly. + + +# Bitfields + +For a bit-packed struct +``` +struct S +{ + uint8_t before; + int j : 5; + int k : 6; + int m : 5; + uint8_t p; + int n : 8; + uint8_t after; +}; ``` -Documentation updated on September 29, 2021 \ No newline at end of file +The fields table looks like this: + +![bit_packed_fields](Images/bit_packed_struct.png "symbols-table") + +Notice for the bitpacked fields(j,k,m,n) the bit_offset and bit_size columns are nonzero. + + +# Docker Dev Environment + +It is often useful to use a virtualized environment for development. There are several recipes on this repo that make this easier. +For example `make docker-ubuntu22-build-dev` will start a dev environment inside of Docker with Ubuntu22. +The repo is mounted as a volume under "/home/docker/juicer" so developers can make their changes on the host and build inside the container. + + + +Documentation updated on September 19, 2024 \ No newline at end of file diff --git a/clang_format_all.py b/clang_format_all.py index 2b043d01..768af692 100644 --- a/clang_format_all.py +++ b/clang_format_all.py @@ -22,7 +22,7 @@ def parse_args(): return args -def check_all_walk_recursive(root_dir: str, exclude_files=None, file_extensions=None): +def check_all_walk_recursive(clang_format_command: str, root_dir: str, exclude_files=None, file_extensions=None): if exclude_files is None: exclude_files = set() if file_extensions is None: @@ -31,13 +31,13 @@ def check_all_walk_recursive(root_dir: str, exclude_files=None, file_extensions= for root, dirs, files in os.walk(root_dir): if dirs: for d in dirs: - check_all_walk_recursive((os.path.join(root, d)), exclude_files, file_extensions) + check_all_walk_recursive(clang_format_command, (os.path.join(root, d)), exclude_files, file_extensions) for file in files: path = Path(os.path.join(root, file)) if str(path) in exclude_files: continue if path.suffix in file_extensions: - if subprocess.run(["clang-format-18", "--dry-run", "--Werror", "-style=file", + if subprocess.run([clang_format_command, "--dry-run", "--Werror", "-style=file", path]).returncode != 0: logger.info("\"%s\": does not comply to format according to clang-format", path) exit(-1) @@ -45,7 +45,7 @@ def check_all_walk_recursive(root_dir: str, exclude_files=None, file_extensions= logger.info("\"%s\": looks fine according to clang-format", path) -def format_all_walk_recursive(root_dir: str, exclude_files=None, file_extensions=None): +def format_all_walk_recursive(clang_format_command: str, root_dir: str, exclude_files=None, file_extensions=None): if exclude_files is None: exclude_files = set() if file_extensions is None: @@ -53,13 +53,13 @@ def format_all_walk_recursive(root_dir: str, exclude_files=None, file_extensions for root, dirs, files in os.walk(root_dir): if dirs: for d in dirs: - format_all_walk_recursive((os.path.join(root, d)), file_extensions) + format_all_walk_recursive(clang_format_command, (os.path.join(root, d)), file_extensions) for file in files: path = Path(os.path.join(root, file)) if str(path) in exclude_files: continue if path.suffix in file_extensions: - if subprocess.run(["clang-format-18", "-style=file", "-i", + if subprocess.run([clang_format_command, "-style=file", "-i", path], capture_output=True).returncode != 0: logger.info("\"%s\": An error occurred while parsing this file.", path) exit(-1) @@ -107,8 +107,8 @@ def main(): excluded_dirs = get_resolved_paths(config['exclude_dirs'], config["root_dir"]) if config['check_all'] is True: - check_all_walk_recursive(str(Path(config["root_dir"]).resolve()), excluded_dirs, config['file_extensions']) + check_all_walk_recursive(config["clang_format_command"], str(Path(config["root_dir"]).resolve()), excluded_dirs, config['file_extensions']) else: - format_all_walk_recursive(str(Path(config["root_dir"]).resolve()), excluded_dirs, config['file_extensions']) + format_all_walk_recursive(config["clang_format_command"], str(Path(config["root_dir"]).resolve()), excluded_dirs, config['file_extensions']) main() \ No newline at end of file diff --git a/clang_format_all_config.yaml b/clang_format_all_config.yaml index ce9e6445..8d0a0157 100644 --- a/clang_format_all_config.yaml +++ b/clang_format_all_config.yaml @@ -1,4 +1,5 @@ -root_dir: "src" +clang_format_command: "clang-format" +root_dir: "." #When true, files will only be checked. None will be modified. check_all: true @@ -21,4 +22,5 @@ exclude_dirs: - "lc" - "prmlib" - "cfs_lib" - - "vm" \ No newline at end of file + - "vm" + - "Catch2" \ No newline at end of file diff --git a/clang_format_all_config_format.yaml b/clang_format_all_config_format.yaml index 4c1c68b5..ab78a0be 100644 --- a/clang_format_all_config_format.yaml +++ b/clang_format_all_config_format.yaml @@ -1,4 +1,5 @@ -root_dir: "src" +root_dir: "." +clang_format_command: "clang-format" #When true, files will only be checked. None will be modified. check_all: false @@ -21,4 +22,5 @@ exclude_dirs: - "lc" - "prmlib" - "cfs_lib" - - "vm" \ No newline at end of file + - "vm" + - "Catch2" \ No newline at end of file diff --git a/docs/DWARF4.pdf b/docs/DWARF4.pdf new file mode 100644 index 00000000..79457c34 Binary files /dev/null and b/docs/DWARF4.pdf differ diff --git a/juicer.files b/juicer.files index f6bb36be..98d2054c 100644 --- a/juicer.files +++ b/juicer.files @@ -291,6 +291,8 @@ src/ElfFile.cpp src/ElfFile.h src/ElfSection.cpp src/ElfSection.h +src/Encoding.cpp +src/Encoding.h src/Enumeration.cpp src/Enumeration.h src/Field.cpp diff --git a/src/Artifact.cpp b/src/Artifact.cpp index 711c75ed..a75c62b6 100644 --- a/src/Artifact.cpp +++ b/src/Artifact.cpp @@ -25,7 +25,6 @@ void Artifact::setId(uint32_t newID) { id = newID; } uint32_t Artifact::getId() { return id; } std::string Artifact::getFilePath() const { return filePath; } -ElfFile& Artifact::getElf() { return elf; } void Artifact::setMD5(std::string newCRC) { md5 = newCRC; } std::string Artifact::getMD5() const { return md5; } diff --git a/src/Artifact.h b/src/Artifact.h index cc1ebf4f..ae4daaed 100644 --- a/src/Artifact.h +++ b/src/Artifact.h @@ -8,6 +8,7 @@ #ifndef SRC_ARTIFACT_H_ #define SRC_ARTIFACT_H_ +#include #include class ElfFile; @@ -33,7 +34,6 @@ class Artifact std::string getMD5() const; std::string getFilePath() const; - ElfFile &getElf(); ~Artifact(); }; diff --git a/src/DefineMacro.cpp b/src/DefineMacro.cpp index 4aa51e57..6b55afa4 100644 --- a/src/DefineMacro.cpp +++ b/src/DefineMacro.cpp @@ -14,12 +14,8 @@ DefineMacro::DefineMacro(std::string inName, std::string inValue) : name{inName} const std::string& DefineMacro::getName() const { return name; } -void DefineMacro::setName(const std::string& name) { this->name = name; } - const std::string& DefineMacro::getValue() const { return value; } -void DefineMacro::setValue(const std::string& value) { this->value = value; } - DefineMacro::~DefineMacro() { // TODO Auto-generated destructor stub diff --git a/src/DefineMacro.h b/src/DefineMacro.h index 0378a4f5..9b63a5cb 100644 --- a/src/DefineMacro.h +++ b/src/DefineMacro.h @@ -17,12 +17,8 @@ class DefineMacro const std::string& getName() const; - void setName(const std::string& name); - const std::string& getValue() const; - void setValue(const std::string& value); - virtual ~DefineMacro(); private: diff --git a/src/DimensionList.cpp b/src/DimensionList.cpp index 08844c2d..d4f4e71c 100644 --- a/src/DimensionList.cpp +++ b/src/DimensionList.cpp @@ -63,11 +63,6 @@ std::string DimensionList::toString() return dimListStr; } - -uint32_t DimensionList::getId() const { return id; } - -void DimensionList::setId(uint32_t id) { this->id = id; } - void DimensionList::addDimension(uint32_t upperBound) { dimensions.push_back(Dimension{upperBound}); } const std::vector& DimensionList::getDimensions() const { return dimensions; } diff --git a/src/DimensionList.h b/src/DimensionList.h index 0a1cfec2..c9a6691d 100644 --- a/src/DimensionList.h +++ b/src/DimensionList.h @@ -90,12 +90,9 @@ class DimensionList std::string toString(); void addDimension(uint32_t inUpperBound); - uint32_t getId() const; - void setId(uint32_t id); const std::vector& getDimensions() const; private: - uint32_t id{}; std::vector dimensions{}; }; diff --git a/src/Elf64Symbol.cpp b/src/Elf64Symbol.cpp new file mode 100644 index 00000000..a707d6fe --- /dev/null +++ b/src/Elf64Symbol.cpp @@ -0,0 +1,12 @@ +#include "Elf64Symbol.h" + +Elf64Symbol::Elf64Symbol(Elf64_Sym newSymbol, uint32_t newFileOffset, uint32_t newStrTableFileOffset) + : symbol{newSymbol}, fileOffset{newFileOffset}, strTableFileOffset{newStrTableFileOffset} +{ +} + +Elf64_Sym Elf64Symbol::getSymbol() const { return symbol; } + +uint32_t Elf64Symbol::getFileOffset() const { return fileOffset; } + +uint32_t Elf64Symbol::getStrTableFileOffset() const { return strTableFileOffset; } diff --git a/src/Elf64Symbol.h b/src/Elf64Symbol.h new file mode 100644 index 00000000..ae9cc9d3 --- /dev/null +++ b/src/Elf64Symbol.h @@ -0,0 +1,26 @@ +#ifndef ELF64SYMBOL_H +#define ELF64SYMBOL_H + +#include + +/** + * @brief The Elf32Symbol class + * Extension of Elf32_Sym struct. Makes it easier to map symbol sections + * to file offsets. + */ + +class Elf64Symbol +{ + private: + Elf64_Sym symbol; + uint32_t fileOffset; + uint32_t strTableFileOffset; + + public: + Elf64_Sym getSymbol() const; + uint32_t getStrTableFileOffset() const; + uint32_t getFileOffset() const; + Elf64Symbol(Elf64_Sym newSymbol, uint32_t newFileOffset, uint32_t newStrTableFileOffset); +}; + +#endif // ELF32SYMBOL_H diff --git a/src/ElfFile.cpp b/src/ElfFile.cpp index 3e7a7cfa..c78c42cd 100644 --- a/src/ElfFile.cpp +++ b/src/ElfFile.cpp @@ -26,37 +26,15 @@ ElfFile::ElfFile(std::string& inName) logger.logDebug("Elf '%s' created.", getName().c_str()); } -ElfFile::ElfFile() : name{""}, id{0} { logger.logError("Cannot call Module default constructor."); } - -ElfFile::ElfFile(const ElfFile& elf) - : name{elf.name}, // @suppress("Symbol is not resolved") - id{0} -{ - logger.logError("Cannot call Module copy constructor."); -} - ElfFile::~ElfFile() {} std::string ElfFile::getName() const { return name; } -/** - *@brief - * - *@note Absolute paths are enforced. - */ -void ElfFile::setName(std::string& inName) -{ - logger.logDebug("Module %s renamed to %s.", name.c_str(), inName.c_str()); +uint32_t ElfFile::getId(void) const { return id; } - this->name = inName; - normalizePath(name); -} +void ElfFile::setId(uint32_t newId) { id = newId; } -uint32_t ElfFile::getId(void) const { return id; } - -void ElfFile::setId(uint32_t newId) { id = newId; } - -void ElfFile::isLittleEndian(bool inLittleEndian) +void ElfFile::isLittleEndian(bool inLittleEndian) { logger.logDebug("ELF %s endian changed from %s to %s.", name.c_str(), little_endian ? "LE" : "BE", inLittleEndian ? "LE" : "BE"); @@ -107,32 +85,21 @@ Symbol* ElfFile::getSymbol(std::string& name) return returnSymbol; } -bool ElfFile::isSymbolUnique(std::string& name) +Symbol* ElfFile::addSymbol(std::string& inName, uint32_t inByteSize, Artifact newArtifact, Symbol* targetSymbol) { - bool rc = false; - Symbol* symbol = getSymbol(name); + Symbol* symbol = getSymbol(inName); if (symbol == nullptr) { - rc = true; - } - else - { - rc = false; - - logger.logDebug("isSymbolUnique is false."); - } - - return rc; -} + std::unique_ptr newSymbol = std::make_unique(*this, inName, inByteSize, newArtifact); + newSymbol->setTargetSymbol(targetSymbol); -Symbol* ElfFile::addSymbol(std::unique_ptr inSymbol) -{ - logger.logDebug("Adding Symbol %s to Module %s.", inSymbol->getName().c_str(), name.c_str()); + symbols.push_back(std::move(newSymbol)); - symbols.push_back(std::move(inSymbol)); + symbol = symbols.back().get(); + } - return symbols.back().get(); + return symbol; } Symbol* ElfFile::addSymbol(std::string& inName, uint32_t inByteSize, Artifact newArtifact) @@ -209,9 +176,8 @@ void ElfFile::normalizePath(std::string& path) path.insert(0, resolvedPath); } -void ElfFile::addDefineMacro(std::string name, std::string value) { defineMacros.push_back(DefineMacro{name, value}); } -void ElfFile::addDefineMacro(DefineMacro newMacro) { defineMacros.push_back(newMacro); } -const std::vector& ElfFile::getDefineMacros() const { return defineMacros; } +void ElfFile::addDefineMacro(DefineMacro newMacro) { defineMacros.push_back(newMacro); } +const std::vector& ElfFile::getDefineMacros() const { return defineMacros; } const std::map>& ElfFile::getInitializedSymbolData() const { return initializedSymbolData; } void ElfFile::setInitializedSymbolData(const std::map>& initializedSymbolData) @@ -224,8 +190,52 @@ void ElfFile::addVariable(Variable newVariable) { variab const std::vector& ElfFile::getVariables() const { return variables; } void ElfFile::addElf32SectionHeader(Elf32_Shdr newSectionHeader) { elf32Headers.push_back(newSectionHeader); } +void ElfFile::addElf64SectionHeader(Elf64_Shdr newSectionHeader) { elf64Headers.push_back(newSectionHeader); } std::vector ElfFile::getElf32Headers() const { return elf32Headers; } +std::vector ElfFile::getElf64Headers() const { return elf64Headers; } void ElfFile::addElf32SymbolTableSymbol(Elf32Symbol newSymbol) { elf32SymbolTable.push_back(newSymbol); } std::vector ElfFile::getElf32SymbolTable() const { return elf32SymbolTable; } + +void ElfFile::addElf64SymbolTableSymbol(Elf64Symbol newSymbol) { elf64SymbolTable.push_back(newSymbol); } +std::vector ElfFile::getElf64SymbolTable() const { return elf64SymbolTable; } + +/** + * @brief ElfFile::getEncodings + * @return a list of encodings as per DWARF5 specification document section 5.1.1 titled "Base Type Encodings" + */ +std::vector ElfFile::getDWARFEncodings() +{ + std::vector encodings{}; + + for (std::pair e : encodingsMap) + { + encodings.push_back(e.second); + } + return encodings; +} + +/** + * @brief ElfFile::getDWARFEncoding + * @param encoding + * @todo add error-checking since we know the valid values + * @return + */ +Encoding& ElfFile::getDWARFEncoding(int encoding) { return encodingsMap.at(encoding); } + +void ElfFile::setElfClass(int newelfClass) +{ + switch (newelfClass) + { + case ELFCLASS32: + case ELFCLASS64: + elfClass = newelfClass; + break; + default: + elfClass = newelfClass; + logger.logWarning("Invalid elf class set:%d", elfClass); + } +} + +int ElfFile::getElfClass() { return elfClass; } diff --git a/src/ElfFile.h b/src/ElfFile.h index 82990b7f..c6e236ac 100644 --- a/src/ElfFile.h +++ b/src/ElfFile.h @@ -16,10 +16,13 @@ #include "DefineMacro.h" #include "Elf32Symbol.h" +#include "Elf64Symbol.h" +#include "Encoding.h" #include "Field.h" #include "Juicer.h" #include "Logger.h" #include "Variable.h" +#include "dwarf.h" class Symbol; class Field; @@ -41,21 +44,17 @@ class Variable; class ElfFile { public: - ElfFile(); ElfFile(std::string &name); - ElfFile(const ElfFile &elf); virtual ~ElfFile(); std::vector> &getSymbols(); std::string getName() const; - void setName(std::string &name); uint32_t getId(void) const; void setId(uint32_t newId); - Symbol *addSymbol(std::unique_ptr symbol); 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(); - bool isSymbolUnique(std::string &name); Symbol *getSymbol(std::string &name); const std::string &getDate() const; void setDate(const std::string &date); @@ -63,7 +62,6 @@ class ElfFile void isLittleEndian(bool littleEndian); void setMD5(std::string newID); std::string getMD5() const; - void addDefineMacro(std::string name, std::string value); void addDefineMacro(DefineMacro newMacro); const std::vector &getDefineMacros() const; @@ -76,9 +74,23 @@ class ElfFile void addElf32SectionHeader(Elf32_Shdr newVariable); std::vector getElf32Headers() const; + void addElf64SectionHeader(Elf64_Shdr newVariable); + std::vector getElf64Headers() const; + void addElf32SymbolTableSymbol(Elf32Symbol newSymbol); std::vector getElf32SymbolTable() const; + void addElf64SymbolTableSymbol(Elf64Symbol newSymbol); + std::vector getElf64SymbolTable() const; + + std::vector getDWARFEncodings(); + + Encoding &getDWARFEncoding(int encoding); + + int getElfClass(); + + void setElfClass(int newelfClass); + private: std::string md5; /** @@ -110,6 +122,49 @@ class ElfFile std::vector elf32SymbolTable{}; std::vector elf32StringsTable{}; + + std::vector elf64SymbolTable{}; + std::vector elf64StringsTable{}; + + /** + * @note This list of encodings can be found in dwarf.h or + * in DWARF5 specification document section 5.1.1 titled "Base Type Encodings" + */ + /** + * @brief encodingMap maps the DWARF macros to strings. + */ + std::map encodingsMap = { + {DW_ATE_address, Encoding{"DW_ATE_address"}}, + {DW_ATE_boolean, Encoding{"DW_ATE_boolean"}}, + {DW_ATE_complex_float, Encoding{"DW_ATE_complex_float"}}, + {DW_ATE_float, Encoding{"DW_ATE_float"}}, + {DW_ATE_signed, Encoding{"DW_ATE_signed"}}, + {DW_ATE_signed_char, Encoding{"DW_ATE_signed_char"}}, + {DW_ATE_unsigned, Encoding{"DW_ATE_unsigned"}}, + {DW_ATE_unsigned_char, Encoding{"DW_ATE_unsigned_char"}}, + {DW_ATE_imaginary_float, Encoding{"DW_ATE_imaginary_float"}}, + {DW_ATE_packed_decimal, Encoding{"DW_ATE_packed_decimal"}}, + {DW_ATE_numeric_string, Encoding{"DW_ATE_numeric_string"}}, + {DW_ATE_edited, Encoding{"DW_ATE_edited"}}, + {DW_ATE_signed_fixed, Encoding{"DW_ATE_signed_fixed"}}, + {DW_ATE_unsigned_fixed, Encoding{"DW_ATE_unsigned_fixed"}}, + {DW_ATE_decimal_float, Encoding{"DW_ATE_decimal_float"}}, + {DW_ATE_UTF, Encoding{"DW_ATE_UTF"}}, + {DW_ATE_UCS, Encoding{"DW_ATE_UCS"}}, + {DW_ATE_ASCII, Encoding{"DW_ATE_ASCII"}}, + + }; + + Encoding &getDWARFEncoding(); + + /** + * @brief elfClass + * as per the libelf defines + * #define ELFCLASSNONE 0 Invalid class + * #define ELFCLASS32 1 32-bit objects + * #define ELFCLASS64 2 64-bit objects + */ + int elfClass{ELFCLASSNONE}; }; #endif /* ElfFile_H_ */ diff --git a/src/ElfSection.cpp b/src/ElfSection.cpp deleted file mode 100644 index 20b7fce7..00000000 --- a/src/ElfSection.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "ElfSection.h" - -ElfSection::ElfSection() {} diff --git a/src/ElfSection.h b/src/ElfSection.h deleted file mode 100644 index 4feb7960..00000000 --- a/src/ElfSection.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef ELFSECTION_H -#define ELFSECTION_H -#include -#include - -#include - -class ElfSection -{ - public: - ElfSection(); - - private: - std::string sectionName; - uint32_t fileOffset; - uint32_t sectionType; // See elf.h for legal values of sh_type - - Elf32_Shdr elf32_Header; -}; - -#endif // ELFSECTION_H diff --git a/src/Encoding.cpp b/src/Encoding.cpp new file mode 100644 index 00000000..c73499d7 --- /dev/null +++ b/src/Encoding.cpp @@ -0,0 +1,9 @@ +#include "Encoding.h" + +Encoding::Encoding(std::string name) : name{name} {} + +std::string& Encoding::getName() { return name; } + +void Encoding::setId(int newId) { id = newId; } + +int Encoding::getId() const { return id; } diff --git a/src/Encoding.h b/src/Encoding.h new file mode 100644 index 00000000..6529787f --- /dev/null +++ b/src/Encoding.h @@ -0,0 +1,26 @@ +#ifndef ENCODING_H +#define ENCODING_H + +#include + +/** + * @brief The Encoding class + * Simple wrapper for DWARF5 encoding macros. + * Read DWARF5 specification document section 5.1.1 titled "Base Type Encodings" + * for more details. + */ + +class Encoding +{ + public: + Encoding(std::string name); + std::string& getName(); + void setId(int); + int getId() const; + + private: + std::string name; + int id; +}; + +#endif // ENCODING_H diff --git a/src/Enumeration.cpp b/src/Enumeration.cpp index f23960d4..ab9cc85e 100644 --- a/src/Enumeration.cpp +++ b/src/Enumeration.cpp @@ -27,13 +27,6 @@ Enumeration::Enumeration(Symbol& inSymbol, std::string& inName, int64_t inValue) logger.logDebug("ENUM %s:%s value:%u created.", symbol.getName().c_str(), name.c_str(), value); } -Enumeration::Enumeration(Enumeration& inEnumeration) - : symbol{inEnumeration.getSymbol()}, // @suppress("Symbol is not resolved") - name{inEnumeration.getName()}, // @suppress("Symbol is not resolved") - value{inEnumeration.getValue()} -{ -} - Enumeration::~Enumeration() {} std::string& Enumeration::getName() { return name; } diff --git a/src/Enumeration.h b/src/Enumeration.h index b3cd4f95..120e9b08 100644 --- a/src/Enumeration.h +++ b/src/Enumeration.h @@ -21,7 +21,6 @@ class Enumeration Enumeration(Symbol& symbol); Enumeration(Symbol& symbol, std::string& name, int64_t value); virtual ~Enumeration(); - Enumeration(Enumeration& enumeration); std::string& getName(); void setName(std::string& name); Symbol& getSymbol(); diff --git a/src/Field.cpp b/src/Field.cpp index 3c6f28f6..c7dadcd9 100644 --- a/src/Field.cpp +++ b/src/Field.cpp @@ -18,7 +18,7 @@ Field::Field(Symbol& inSymbol, Symbol& inType) short_description{""}, long_description{""} { - logger.logDebug("Field %s::%s byte_offset=%u type=%s multiplicity=%d endian=%s created.", symbol.getName().c_str(), name.c_str(), byte_offset, + logger.logDebug("Field %s::%s byte_offset=%u type=%s multiplicity=%s endian=%s created.", symbol.getName().c_str(), name.c_str(), byte_offset, type.getName().c_str(), dimensionList.toString(), little_endian ? "LE" : "BE"); } @@ -30,15 +30,15 @@ Field::Field(Symbol& inSymbol, std::string& inName, uint32_t inByteOffset, Symbo type{inType}, // @suppress("Symbol is not resolved") dimensionList{inDimensionList}, little_endian{inLittleEndian}, - bit_offset{inBitSize}, + bit_offset{inBitOffset}, bit_size{inBitSize}, id{0}, short_description{""}, long_description{""} { - logger.logDebug("Field %s::%s byte_offset=%u type=%s multiplicity=%d endian=%s created.", symbol.getName().c_str(), name.c_str(), byte_offset, - type.getName().c_str(), dimensionList, little_endian ? "LE" : "BE"); + logger.logDebug("Field %s::%s byte_offset=%u type=%s multiplicity=%s endian=%s created.", symbol.getName().c_str(), name.c_str(), byte_offset, + 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) @@ -48,49 +48,21 @@ Field::Field(Symbol& inSymbol, std::string& inName, uint32_t inByteOffset, Symbo type{inType}, // @suppress("Symbol is not resolved") dimensionList{}, little_endian{inLittleEndian}, - bit_offset{inBitSize}, + bit_offset{inBitOffset}, bit_size{inBitSize}, id{0}, short_description{""}, long_description{""} { - logger.logDebug("Field %s::%s byte_offset=%u type=%s multiplicity=%d endian=%s created.", symbol.getName().c_str(), name.c_str(), byte_offset, - type.getName().c_str(), dimensionList, little_endian ? "LE" : "BE"); -} - -Field::Field(Field& field) - : symbol{field.getSymbol()}, // @suppress("Symbol is not resolved") - name{field.getName()}, // @suppress("Symbol is not resolved") - byte_offset{field.getByteOffset()}, - type{field.getType()}, // @suppress("Symbol is not resolved") - dimensionList(field.getDimensionList()), - little_endian{field.isLittleEndian()}, - short_description{""}, - long_description{""} -{ + logger.logDebug("Field %s::%s byte_offset=%u type=%s multiplicity=%s endian=%s created.", symbol.getName().c_str(), name.c_str(), byte_offset, + type.getName().c_str(), dimensionList.toString(), little_endian ? "LE" : "BE"); } - Field::~Field() {} -uint32_t Field::getByteOffset() const { return byte_offset; } +uint32_t Field::getByteOffset() const { return byte_offset; } -void Field::setByteOffset(uint32_t inByteOffset) -{ - logger.logDebug("Field %s::%s byte_offset changed from %u to %u.", symbol.getName().c_str(), name.c_str(), byte_offset, inByteOffset); - - byte_offset = inByteOffset; -} - -bool Field::isLittleEndian() const { return little_endian; } - -void Field::setLittleEndian(bool inLittleEndian) -{ - logger.logDebug("Field %s::%s endian changed from %s to %s.", symbol.getName().c_str(), name.c_str(), little_endian ? "LE" : "BE", - inLittleEndian ? "LE" : "BE"); - - little_endian = inLittleEndian; -} +bool Field::isLittleEndian() const { return little_endian; } std::string& Field::getName() { return name; } diff --git a/src/Field.h b/src/Field.h index 4fed1066..fa6797f6 100644 --- a/src/Field.h +++ b/src/Field.h @@ -34,24 +34,21 @@ class Field 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; - void setByteOffset(uint32_t byteOffset); - bool isLittleEndian() const; - void setLittleEndian(bool littleEndian); - 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); - Field(Field &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; diff --git a/src/IDataContainer.cpp b/src/IDataContainer.cpp index b616ef88..b1fde9c0 100644 --- a/src/IDataContainer.cpp +++ b/src/IDataContainer.cpp @@ -87,35 +87,3 @@ IDataContainer *IDataContainer::Create(IDataContainer_Type_t containerType, cons return container; } - -std::string IDataContainer::vstring(const char *format, ...) -{ - std::string result; - va_list args, args_copy; - - va_start(args, format); - va_copy(args_copy, args); - - int len = vsnprintf(nullptr, 0, format, args); - if (len < 0) - { - va_end(args_copy); - va_end(args); - throw std::runtime_error("vsnprintf error"); - } - - if (len > 0) - { - result.resize(len); - // note: &result[0] is *guaranteed* only in C++11 and later - // to point to a buffer of contiguous memory with room for a - // null-terminator, but this "works" in earlier versions - // in *most* common implementations as well... - vsnprintf(&result[0], len + 1, format, args_copy); // or result.data() in C++17 and later... - } - - va_end(args_copy); - va_end(args); - - return result; -} diff --git a/src/IDataContainer.h b/src/IDataContainer.h index b8942f46..810e4937 100644 --- a/src/IDataContainer.h +++ b/src/IDataContainer.h @@ -38,8 +38,7 @@ class IDataContainer virtual int initialize(std::string& initString) = 0; private: - static Logger logger; - static std::string vstring(const char* format, ...); + static Logger logger; }; #endif /* IDATACONTAINER_H_ */ diff --git a/src/Juicer.cpp b/src/Juicer.cpp index e9b1e9b3..6b011fdd 100644 --- a/src/Juicer.cpp +++ b/src/Juicer.cpp @@ -69,148 +69,6 @@ struct macro_counts_s long mc_unknown; }; -static void print_one_macro_entry_detail(long i, char *type, struct Dwarf_Macro_Details_s *mdp) -{ - /* "DW_MACINFO_*: section-offset file-index [line] string\n" */ - if (mdp->dmd_macro) - { - printf("%3ld %s: %6" DW_PR_DUu " %2" DW_PR_DSd " [%4" DW_PR_DSd "] \"%s\" \n", i, type, (Dwarf_Unsigned)mdp->dmd_offset, mdp->dmd_fileindex, - mdp->dmd_lineno, mdp->dmd_macro); - } - else - { - printf("%3ld %s: %6" DW_PR_DUu " %2" DW_PR_DSd " [%4" DW_PR_DSd "] 0\n", i, type, (Dwarf_Unsigned)mdp->dmd_offset, mdp->dmd_fileindex, mdp->dmd_lineno); - } -} - -static void print_one_macro_entry(long i, struct Dwarf_Macro_Details_s *mdp, struct macro_counts_s *counts) -{ - switch (mdp->dmd_type) - { - case 0: - counts->mc_code_zero++; - print_one_macro_entry_detail(i, "DW_MACINFO_type-code-0", mdp); - break; - - case DW_MACINFO_start_file: - counts->mc_start_file++; - print_one_macro_entry_detail(i, "DW_MACINFO_start_file", mdp); - break; - - case DW_MACINFO_end_file: - counts->mc_end_file++; - print_one_macro_entry_detail(i, "DW_MACINFO_end_file ", mdp); - break; - - case DW_MACINFO_vendor_ext: - counts->mc_extension++; - print_one_macro_entry_detail(i, "DW_MACINFO_vendor_ext", mdp); - break; - - case DW_MACINFO_define: - counts->mc_define++; - print_one_macro_entry_detail(i, "DW_MACINFO_define ", mdp); - break; - - case DW_MACINFO_undef: - counts->mc_undef++; - print_one_macro_entry_detail(i, "DW_MACINFO_undef ", mdp); - break; - - default: - { - char create_type[50]; /* More than large enough. */ - - counts->mc_unknown++; - snprintf(create_type, sizeof(create_type), "DW_MACINFO_0x%x", mdp->dmd_type); - print_one_macro_entry_detail(i, create_type, mdp); - } - break; - } -} - -/* print data in .debug_macinfo */ -/* FIXME: should print name of file whose index is in macro data - here -- somewhere. */ -/*ARGSUSED*/ extern void print_macinfo(Dwarf_Debug dbg, Dwarf_Error err) -{ - Dwarf_Off offset = 0; - Dwarf_Unsigned max = 10; - Dwarf_Signed count = 0; - long group = 0; - Dwarf_Macro_Details *maclist = NULL; - int lres = 0; - - bool do_print_dwarf = true; - if (!do_print_dwarf) - { - return; - } - - printf("\n.debug_macinfo\n"); - - while ((lres = dwarf_get_macro_details(dbg, offset, max, &count, &maclist, &err)) == DW_DLV_OK) - { - printf("\n.debug_macinfo2\n"); - long i = 0; - struct macro_counts_s counts; - - memset(&counts, 0, sizeof(counts)); - - printf("\n"); - printf("compilation-unit .debug_macinfo # %ld\n", group); - printf("num name section-offset file-index [line] \"string\"\n"); - for (i = 0; i < count; i++) - { - struct Dwarf_Macro_Details_s *mdp = &maclist[i]; - - print_one_macro_entry(i, mdp, &counts); - } - - if (counts.mc_start_file == 0) - { - printf("DW_MACINFO file count of zero is invalid DWARF2/3\n"); - } - if (counts.mc_start_file != counts.mc_end_file) - { - printf( - "Counts of DW_MACINFO file (%ld) end_file (%ld) " - "do not match!.\n", - counts.mc_start_file, counts.mc_end_file); - } - if (counts.mc_code_zero < 1) - { - printf( - "Count of zeros in macro group should be non-zero " - "(1 preferred), count is %ld\n", - counts.mc_code_zero); - } - printf( - "Macro counts: start file %ld, " - "end file %ld, " - "define %ld, " - "undef %ld, " - "ext %ld, " - "code-zero %ld, " - "unknown %ld\n", - counts.mc_start_file, counts.mc_end_file, counts.mc_define, counts.mc_undef, counts.mc_extension, counts.mc_code_zero, counts.mc_unknown); - - /* int type= maclist[count - 1].dmd_type; */ - /* ASSERT: type is zero */ - - offset = maclist[count - 1].dmd_offset + 1; - dwarf_dealloc(dbg, maclist, DW_DLA_STRING); - ++group; - } - if (lres == DW_DLV_ERROR) - { - // std::cout << "dwarf_get_macro_details error" << std::endl; - // print_error(dbg, "dwarf_get_macro_details", lres, err); - } - - printf("\n.debug_macinfo3:%d\n", lres); -} - Juicer::Juicer() {} DefineMacro Juicer::getDefineMacroFromString(std::string macro_string) @@ -306,8 +164,6 @@ DefineMacro Juicer::getDefineMacro(Dwarf_Half macro_operator, Dwarf_Macro_Contex case DW_MACRO_import: { res = dwarf_get_macro_import(mac_context, i, &offset, &error); - printf("dwarf_get_macro_import res:%d\n", res); - printf("dwarf_get_macro_import offset:%d\n", offset); if (offset == 0) { @@ -409,8 +265,6 @@ int Juicer::readCUList(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Error &error) logger.logDebug("Reading CU %u.", cu_number); - print_macinfo(dbg, error); - DisplayDie(cu_die, 0); Dwarf_Unsigned mac_version; @@ -842,9 +696,18 @@ Symbol *Juicer::process_DW_TAG_pointer_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf if (pathIndex != 0) { + /** + * Why we are checking against 0 as per DWARF section 2.14: + * + * The value of the DW_AT_decl_file attribute corresponds to a file number from the line number + * information table for the compilation unit containing the debugging information entry and + * represents the source file in which the declaration appeared (see Section 6.2 ). The value 0 + * indicates that no source file has been specified. + * + */ /* This branch represents a "void*" since there is no valid type. * Read section 5.2 of DWARF4 for details on this.*/ - Artifact newArtifact{elf, dbgSourceFiles.at(pathIndex - 1)}; + Artifact newArtifact{elf, getdbgSourceFile(elf, pathIndex)}; std::string checkSum = generateMD5SumForFile(newArtifact.getFilePath()); newArtifact.setMD5(checkSum); outSymbol = elf.addSymbol(voidType, byteSize, newArtifact); @@ -899,9 +762,6 @@ Symbol *Juicer::process_DW_TAG_pointer_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf if (res == DW_DLV_OK) { - unsigned long long pathIndex = 0; - res = dwarf_formudata(attr_struct, &pathIndex, &error); - // TODO: pathIndex will be extracted from the DWARF decl_file attribute. /** * According to 6.2 Line Number Information in DWARF 4: * Line number information generated for a compilation unit is represented in the .debug_line @@ -923,20 +783,11 @@ Symbol *Juicer::process_DW_TAG_pointer_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf * */ - if (pathIndex != 0) - { - Artifact newArtifact{elf, dbgSourceFiles.at(pathIndex - 1)}; - std::string checkSum = generateMD5SumForFile(newArtifact.getFilePath()); - newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(name, byteSize, newArtifact); - } - else - { - Artifact newArtifact{elf, "NOT_FOUND:" + name}; - std::string checkSum{}; - newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(name, byteSize, newArtifact); - } + // As per the DWARF; pointer types do not have any "DECL" attributes, aka declaration coords (line numbers, declaration files, etc). + Artifact newArtifact{elf, "NOT_FOUND:" + name}; + std::string checkSum{}; + newArtifact.setMD5(checkSum); + outSymbol = elf.addSymbol(name, byteSize, newArtifact); } } @@ -1041,10 +892,18 @@ Symbol *Juicer::process_DW_TAG_variable_type(ElfFile &elf, Dwarf_Debug dbg, Dwar if (elf.getInitializedSymbolData().find(outName) != elf.getInitializedSymbolData().end()) { + /** + * @todo variableData might be useful if we want to store the data + * inside the ELF inside of the db. + * CFS tables is an example of this. + * Though it should be noted that the data can be + * extracted by querying the SQL db; query_symbols.py is an example of this. + * + */ std::vector variableData = elf.getInitializedSymbolData().at(outName); - - elf.addVariable(newVariable); } + + elf.addVariable(newVariable); } } } @@ -1219,7 +1078,16 @@ Symbol *Juicer::getBaseTypeSymbol(ElfFile &elf, Dwarf_Die inDie, DimensionList & if (pathIndex != 0) { - Artifact newArtifact{elf, dbgSourceFiles.at(pathIndex - 1)}; + /** + * Why we are checking against 0 as per DWARF section 2.14: + * + * The value of the DW_AT_decl_file attribute corresponds to a file number from the line number + * information table for the compilation unit containing the debugging information entry and + * represents the source file in which the declaration appeared (see Section 6.2 ). The value 0 + * indicates that no source file has been specified. + * + */ + Artifact newArtifact{elf, getdbgSourceFile(elf, pathIndex)}; std::string checkSum = generateMD5SumForFile(newArtifact.getFilePath()); newArtifact.setMD5(checkSum); outSymbol = elf.addSymbol(cName, byteSize, newArtifact); @@ -1383,7 +1251,16 @@ Symbol *Juicer::getBaseTypeSymbol(ElfFile &elf, Dwarf_Die inDie, DimensionList & if (pathIndex != 0) { - Artifact newArtifact{elf, dbgSourceFiles.at(pathIndex - 1)}; + /** + * Why we are checking against 0 as per DWARF section 2.14: + * + * The value of the DW_AT_decl_file attribute corresponds to a file number from the line number + * information table for the compilation unit containing the debugging information entry and + * represents the source file in which the declaration appeared (see Section 6.2 ). The value 0 + * indicates that no source file has been specified. + * + */ + Artifact newArtifact{elf, getdbgSourceFile(elf, pathIndex)}; std::string checkSum = generateMD5SumForFile(newArtifact.getFilePath()); newArtifact.setMD5(checkSum); outSymbol = elf.addSymbol(cName, byteSize, newArtifact); @@ -1397,6 +1274,14 @@ Symbol *Juicer::getBaseTypeSymbol(ElfFile &elf, Dwarf_Die inDie, DimensionList & } } + else + { + Artifact newArtifact{elf, "NOT_FOUND:" + cName}; + std::string checkSum{}; + newArtifact.setMD5(checkSum); + outSymbol = elf.addSymbol(cName, byteSize, newArtifact); + } + process_DW_TAG_enumeration_type(elf, *outSymbol, dbg, typeDie); } break; @@ -1492,1730 +1377,1732 @@ void Juicer::DisplayDie(Dwarf_Die inDie, uint32_t level) char line[255]; Dwarf_Error error = 0; - if (inDie != 0) - { - res = dwarf_tag(inDie, &tag, &error); - if (res == DW_DLV_OK) - { - switch (tag) - { - case DW_TAG_array_type: - sprintf(tagName, "DW_TAG_array_type"); - break; - - case DW_TAG_class_type: - sprintf(tagName, "DW_TAG_class_type"); - break; - - case DW_TAG_entry_point: - sprintf(tagName, "DW_TAG_entry_point"); - break; - - case DW_TAG_enumeration_type: - sprintf(tagName, "DW_TAG_enumeration_type"); - break; - - case DW_TAG_formal_parameter: - sprintf(tagName, "DW_TAG_formal_parameter"); - break; - - case DW_TAG_imported_declaration: - sprintf(tagName, "DW_TAG_imported_declaration"); - break; - - case DW_TAG_label: - sprintf(tagName, "DW_TAG_label"); - break; - - case DW_TAG_lexical_block: - sprintf(tagName, "DW_TAG_lexical_block"); - break; - - case DW_TAG_member: - sprintf(tagName, "DW_TAG_member"); - break; - - case DW_TAG_pointer_type: - sprintf(tagName, "DW_TAG_pointer_type"); - break; - - case DW_TAG_reference_type: - sprintf(tagName, "DW_TAG_reference_type"); - break; - - case DW_TAG_compile_unit: - sprintf(tagName, "DW_TAG_compile_unit"); - break; - - case DW_TAG_string_type: - sprintf(tagName, "DW_TAG_string_type"); - break; - - case DW_TAG_structure_type: - sprintf(tagName, "DW_TAG_structure_type"); - break; - - case DW_TAG_subroutine_type: - sprintf(tagName, "DW_TAG_subroutine_type"); - break; - - case DW_TAG_typedef: - sprintf(tagName, "DW_TAG_typedef"); - break; - - case DW_TAG_union_type: - sprintf(tagName, "DW_TAG_union_type"); - break; - - case DW_TAG_unspecified_parameters: - sprintf(tagName, "DW_TAG_unspecified_parameters"); - break; - - case DW_TAG_variant: - sprintf(tagName, "DW_TAG_variant"); - break; - - case DW_TAG_common_block: - sprintf(tagName, "DW_TAG_common_block"); - break; - - case DW_TAG_common_inclusion: - sprintf(tagName, "DW_TAG_common_inclusion"); - break; - - case DW_TAG_inheritance: - sprintf(tagName, "DW_TAG_inheritance"); - break; - - case DW_TAG_inlined_subroutine: - sprintf(tagName, "DW_TAG_inlined_subroutine"); - break; - - case DW_TAG_module: - sprintf(tagName, "DW_TAG_module"); - break; - - case DW_TAG_ptr_to_member_type: - sprintf(tagName, "DW_TAG_ptr_to_member_type"); - break; - - case DW_TAG_set_type: - sprintf(tagName, "DW_TAG_set_type"); - break; - - case DW_TAG_subrange_type: - sprintf(tagName, "DW_TAG_subrange_type"); - break; - - case DW_TAG_with_stmt: - sprintf(tagName, "DW_TAG_with_stmt"); - break; - - case DW_TAG_access_declaration: - sprintf(tagName, "DW_TAG_access_declaration"); - break; - - case DW_TAG_base_type: - sprintf(tagName, "DW_TAG_base_type"); - break; - - case DW_TAG_catch_block: - sprintf(tagName, "DW_TAG_catch_block"); - break; - - case DW_TAG_const_type: - sprintf(tagName, "DW_TAG_const_type"); - break; - - case DW_TAG_constant: - sprintf(tagName, "DW_TAG_constant"); - break; - - case DW_TAG_enumerator: - sprintf(tagName, "DW_TAG_enumerator"); - break; - - case DW_TAG_file_type: - sprintf(tagName, "DW_TAG_file_type"); - break; - - case DW_TAG_friend: - sprintf(tagName, "DW_TAG_friend"); - break; - - case DW_TAG_namelist: - sprintf(tagName, "DW_TAG_namelist"); - break; - - case DW_TAG_namelist_item: - sprintf(tagName, "DW_TAG_namelist_item"); - break; - - case DW_TAG_packed_type: - sprintf(tagName, "DW_TAG_packed_type"); - break; - - case DW_TAG_subprogram: - sprintf(tagName, "DW_TAG_subprogram"); - break; - - case DW_TAG_template_type_parameter: - sprintf(tagName, "DW_TAG_template_type_parameter"); - break; - - case DW_TAG_template_value_parameter: - sprintf(tagName, "DW_TAG_template_value_parameter"); - break; - - case DW_TAG_thrown_type: - sprintf(tagName, "DW_TAG_thrown_type"); - break; - - case DW_TAG_try_block: - sprintf(tagName, "DW_TAG_try_block"); - break; - - case DW_TAG_variant_part: - sprintf(tagName, "DW_TAG_variant_part"); - break; - - case DW_TAG_variable: - sprintf(tagName, "DW_TAG_variable"); - break; - - case DW_TAG_volatile_type: - sprintf(tagName, "DW_TAG_volatile_type"); - break; - - case DW_TAG_dwarf_procedure: - sprintf(tagName, "DW_TAG_dwarf_procedure"); - break; - - case DW_TAG_restrict_type: - sprintf(tagName, "DW_TAG_restrict_type"); - break; - - case DW_TAG_interface_type: - sprintf(tagName, "DW_TAG_interface_type"); - break; - - case DW_TAG_namespace: - sprintf(tagName, "DW_TAG_namespace"); - break; - - case DW_TAG_imported_module: - sprintf(tagName, "DW_TAG_imported_module"); - break; - - case DW_TAG_unspecified_type: - sprintf(tagName, "DW_TAG_unspecified_type"); - break; - - case DW_TAG_partial_unit: - sprintf(tagName, "DW_TAG_partial_unit"); - break; - - case DW_TAG_imported_unit: - sprintf(tagName, "DW_TAG_imported_unit"); - break; - - case DW_TAG_mutable_type: - sprintf(tagName, "DW_TAG_mutable_type"); - break; - - case DW_TAG_condition: - sprintf(tagName, "DW_TAG_condition"); - break; + // if (inDie != 0) + // { + // res = dwarf_tag(inDie, &tag, &error); + // if (res == DW_DLV_OK) + // { + // switch (tag) + // { + // case DW_TAG_array_type: + // sprintf(tagName, "DW_TAG_array_type"); + // break; + + // case DW_TAG_class_type: + // sprintf(tagName, "DW_TAG_class_type"); + // break; + + // case DW_TAG_entry_point: + // sprintf(tagName, "DW_TAG_entry_point"); + // break; + + // case DW_TAG_enumeration_type: + // sprintf(tagName, "DW_TAG_enumeration_type"); + // break; + + // case DW_TAG_formal_parameter: + // sprintf(tagName, "DW_TAG_formal_parameter"); + // break; + + // case DW_TAG_imported_declaration: + // sprintf(tagName, "DW_TAG_imported_declaration"); + // break; + + // case DW_TAG_label: + // sprintf(tagName, "DW_TAG_label"); + // break; + + // case DW_TAG_lexical_block: + // sprintf(tagName, "DW_TAG_lexical_block"); + // break; + + // case DW_TAG_member: + // sprintf(tagName, "DW_TAG_member"); + // break; + + // case DW_TAG_pointer_type: + // sprintf(tagName, "DW_TAG_pointer_type"); + // break; + + // case DW_TAG_reference_type: + // sprintf(tagName, "DW_TAG_reference_type"); + // break; + + // case DW_TAG_compile_unit: + // sprintf(tagName, "DW_TAG_compile_unit"); + // break; + + // case DW_TAG_string_type: + // sprintf(tagName, "DW_TAG_string_type"); + // break; + + // case DW_TAG_structure_type: + // sprintf(tagName, "DW_TAG_structure_type"); + // break; + + // case DW_TAG_subroutine_type: + // sprintf(tagName, "DW_TAG_subroutine_type"); + // break; + + // case DW_TAG_typedef: + // sprintf(tagName, "DW_TAG_typedef"); + // break; + + // case DW_TAG_union_type: + // sprintf(tagName, "DW_TAG_union_type"); + // break; + + // case DW_TAG_unspecified_parameters: + // sprintf(tagName, "DW_TAG_unspecified_parameters"); + // break; + + // case DW_TAG_variant: + // sprintf(tagName, "DW_TAG_variant"); + // break; + + // case DW_TAG_common_block: + // sprintf(tagName, "DW_TAG_common_block"); + // break; + + // case DW_TAG_common_inclusion: + // sprintf(tagName, "DW_TAG_common_inclusion"); + // break; + + // case DW_TAG_inheritance: + // sprintf(tagName, "DW_TAG_inheritance"); + // break; + + // case DW_TAG_inlined_subroutine: + // sprintf(tagName, "DW_TAG_inlined_subroutine"); + // break; + + // case DW_TAG_module: + // sprintf(tagName, "DW_TAG_module"); + // break; + + // case DW_TAG_ptr_to_member_type: + // sprintf(tagName, "DW_TAG_ptr_to_member_type"); + // break; - case DW_TAG_shared_type: - sprintf(tagName, "DW_TAG_shared_type"); - break; + // case DW_TAG_set_type: + // sprintf(tagName, "DW_TAG_set_type"); + // break; - case DW_TAG_type_unit: - sprintf(tagName, "DW_TAG_type_unit"); - break; + // case DW_TAG_subrange_type: + // sprintf(tagName, "DW_TAG_subrange_type"); + // break; - case DW_TAG_rvalue_reference_type: - sprintf(tagName, "DW_TAG_rvalue_reference_type"); - break; + // case DW_TAG_with_stmt: + // sprintf(tagName, "DW_TAG_with_stmt"); + // break; - case DW_TAG_template_alias: - sprintf(tagName, "DW_TAG_template_alias"); - break; + // case DW_TAG_access_declaration: + // sprintf(tagName, "DW_TAG_access_declaration"); + // break; - case DW_TAG_coarray_type: - sprintf(tagName, "DW_TAG_coarray_type"); - break; + // case DW_TAG_base_type: + // sprintf(tagName, "DW_TAG_base_type"); + // break; - case DW_TAG_generic_subrange: - sprintf(tagName, "DW_TAG_generic_subrange"); - break; + // case DW_TAG_catch_block: + // sprintf(tagName, "DW_TAG_catch_block"); + // break; - case DW_TAG_dynamic_type: - sprintf(tagName, "DW_TAG_dynamic_type"); - break; + // case DW_TAG_const_type: + // sprintf(tagName, "DW_TAG_const_type"); + // break; - case DW_TAG_atomic_type: - sprintf(tagName, "DW_TAG_dynamic_type"); - break; + // case DW_TAG_constant: + // sprintf(tagName, "DW_TAG_constant"); + // break; - case DW_TAG_call_site: - sprintf(tagName, "DW_TAG_call_site"); - break; + // case DW_TAG_enumerator: + // sprintf(tagName, "DW_TAG_enumerator"); + // break; - case DW_TAG_call_site_parameter: - sprintf(tagName, "DW_TAG_call_site_parameter"); - break; + // case DW_TAG_file_type: + // sprintf(tagName, "DW_TAG_file_type"); + // break; - case DW_TAG_skeleton_unit: - sprintf(tagName, "DW_TAG_skeleton_unit"); - break; + // case DW_TAG_friend: + // sprintf(tagName, "DW_TAG_friend"); + // break; - case DW_TAG_immutable_type: - sprintf(tagName, "DW_TAG_immutable_type"); - break; + // case DW_TAG_namelist: + // sprintf(tagName, "DW_TAG_namelist"); + // break; - default: - sprintf(tagName, "UNKNOWN (0x%04x)", tag); - break; - } - } - else - { - sprintf(tagName, "<< error >>"); - } + // case DW_TAG_namelist_item: + // sprintf(tagName, "DW_TAG_namelist_item"); + // break; - res = dwarf_die_offsets(inDie, &globalOffset, &localOffset, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_die_offsets. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); - } + // case DW_TAG_packed_type: + // sprintf(tagName, "DW_TAG_packed_type"); + // break; - abbrevCode = dwarf_die_abbrev_code(inDie); + // case DW_TAG_subprogram: + // sprintf(tagName, "DW_TAG_subprogram"); + // break; - res = dwarf_die_abbrev_children_flag(inDie, &hasChildrenFlag); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_die_abbrev_children_flag. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); - } - else - { - logger.logDebug(" Has children: %s\n", hasChildrenFlag ? "True" : "False"); - } + // case DW_TAG_template_type_parameter: + // sprintf(tagName, "DW_TAG_template_type_parameter"); + // break; - res = dwarf_die_abbrev_children_flag(inDie, &hasChildrenFlag); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_die_abbrev_children_flag. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); - } - else - { - logger.logDebug(" Has children: %s\n", hasChildrenFlag ? "True" : "False"); - } + // case DW_TAG_template_value_parameter: + // sprintf(tagName, "DW_TAG_template_value_parameter"); + // break; - sprintf(line, "<%u><%x>: Abbrev Number: %u (%s)\n", level, globalOffset, abbrevCode, tagName); - strcpy(output, line); + // case DW_TAG_thrown_type: + // sprintf(tagName, "DW_TAG_thrown_type"); + // break; - res = dwarf_attrlist(inDie, &attribs, &attribCount, &error); - if (res != DW_DLV_OK) - { - if (res == DW_DLV_ERROR) - { - logger.logError("Error in dwarf_attrlist. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); - } - else if (res == DW_DLV_NO_ENTRY) - { - logger.logWarning("No Entry in dwarf_attrlist. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); - } - } - else - { - if (attribCount > 0) - { - for (uint32_t i = 0; i < attribCount; ++i) - { - Dwarf_Half attrNum; - char attribName[255]; - char formName[50]; - char value[50]; + // case DW_TAG_try_block: + // sprintf(tagName, "DW_TAG_try_block"); + // break; - strcpy(value, "<< Form Not Supported >>"); + // case DW_TAG_variant_part: + // sprintf(tagName, "DW_TAG_variant_part"); + // break; - res = dwarf_whatattr(attribs[i], &attrNum, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_whatattr. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); - } - else - { - Dwarf_Half formID; + // case DW_TAG_variable: + // sprintf(tagName, "DW_TAG_variable"); + // break; + + // case DW_TAG_volatile_type: + // sprintf(tagName, "DW_TAG_volatile_type"); + // break; + + // case DW_TAG_dwarf_procedure: + // sprintf(tagName, "DW_TAG_dwarf_procedure"); + // break; + + // case DW_TAG_restrict_type: + // sprintf(tagName, "DW_TAG_restrict_type"); + // break; + + // case DW_TAG_interface_type: + // sprintf(tagName, "DW_TAG_interface_type"); + // break; + + // case DW_TAG_namespace: + // sprintf(tagName, "DW_TAG_namespace"); + // break; + + // case DW_TAG_imported_module: + // sprintf(tagName, "DW_TAG_imported_module"); + // break; + + // case DW_TAG_unspecified_type: + // sprintf(tagName, "DW_TAG_unspecified_type"); + // break; + + // case DW_TAG_partial_unit: + // sprintf(tagName, "DW_TAG_partial_unit"); + // break; + + // case DW_TAG_imported_unit: + // sprintf(tagName, "DW_TAG_imported_unit"); + // break; + + // case DW_TAG_mutable_type: + // sprintf(tagName, "DW_TAG_mutable_type"); + // break; + + // case DW_TAG_condition: + // sprintf(tagName, "DW_TAG_condition"); + // break; + + // case DW_TAG_shared_type: + // sprintf(tagName, "DW_TAG_shared_type"); + // break; + + // case DW_TAG_type_unit: + // sprintf(tagName, "DW_TAG_type_unit"); + // break; + + // case DW_TAG_rvalue_reference_type: + // sprintf(tagName, "DW_TAG_rvalue_reference_type"); + // break; + + // case DW_TAG_template_alias: + // sprintf(tagName, "DW_TAG_template_alias"); + // break; + + // case DW_TAG_coarray_type: + // sprintf(tagName, "DW_TAG_coarray_type"); + // break; + + // case DW_TAG_generic_subrange: + // sprintf(tagName, "DW_TAG_generic_subrange"); + // break; + + // case DW_TAG_dynamic_type: + // sprintf(tagName, "DW_TAG_dynamic_type"); + // break; + + // case DW_TAG_atomic_type: + // sprintf(tagName, "DW_TAG_dynamic_type"); + // break; + + // case DW_TAG_call_site: + // sprintf(tagName, "DW_TAG_call_site"); + // break; + + // case DW_TAG_call_site_parameter: + // sprintf(tagName, "DW_TAG_call_site_parameter"); + // break; + + // case DW_TAG_skeleton_unit: + // sprintf(tagName, "DW_TAG_skeleton_unit"); + // break; + + // case DW_TAG_immutable_type: + // sprintf(tagName, "DW_TAG_immutable_type"); + // break; + + // default: + // sprintf(tagName, "UNKNOWN (0x%04x)", tag); + // break; + // } + // } + // else + // { + // sprintf(tagName, "<< error >>"); + // } + + // res = dwarf_die_offsets(inDie, &globalOffset, &localOffset, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_die_offsets. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); + // } + + // abbrevCode = dwarf_die_abbrev_code(inDie); + + // res = dwarf_die_abbrev_children_flag(inDie, &hasChildrenFlag); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_die_abbrev_children_flag. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); + // } + // else + // { + // logger.logDebug(" Has children: %s\n", hasChildrenFlag ? "True" : "False"); + // } + + // res = dwarf_die_abbrev_children_flag(inDie, &hasChildrenFlag); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_die_abbrev_children_flag. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); + // } + // else + // { + // logger.logDebug(" Has children: %s\n", hasChildrenFlag ? "True" : "False"); + // } + + // sprintf(line, "<%u><%x>: Abbrev Number: %u (%s)\n", level, globalOffset, abbrevCode, tagName); + // strcpy(output, line); + + // res = dwarf_attrlist(inDie, &attribs, &attribCount, &error); + // if (res != DW_DLV_OK) + // { + // if (res == DW_DLV_ERROR) + // { + // logger.logError("Error in dwarf_attrlist. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); + // } + // else if (res == DW_DLV_NO_ENTRY) + // { + // logger.logWarning("No Entry in dwarf_attrlist. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); + // } + // } + // else + // { + // if (attribCount > 0) + // { + // for (uint32_t i = 0; i < attribCount; ++i) + // { + // Dwarf_Half attrNum; + // char attribName[255]; + // char formName[50]; + // char value[50]; + + // strcpy(value, "<< Form Not Supported >>"); + + // res = dwarf_whatattr(attribs[i], &attrNum, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_whatattr. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); + // } + // else + // { + // Dwarf_Half formID; + + // switch (attrNum) + // { + // case DW_AT_sibling: + // strcpy(attribName, "DW_AT_sibling"); + // break; + + // case DW_AT_location: + // strcpy(attribName, "DW_AT_location"); + // break; + + // case DW_AT_name: + // strcpy(attribName, "DW_AT_name"); + // break; + + // case DW_AT_ordering: + // strcpy(attribName, "DW_AT_ordering"); + // break; + + // case DW_AT_subscr_data: + // strcpy(attribName, "DW_AT_subscr_data"); + // break; + + // case DW_AT_byte_size: + // strcpy(attribName, "DW_AT_byte_size"); + // break; + + // case DW_AT_bit_offset: + // strcpy(attribName, "DW_AT_bit_offset"); + // break; + + // case DW_AT_bit_size: + // strcpy(attribName, "DW_AT_bit_size"); + // break; + + // case DW_AT_element_list: + // strcpy(attribName, "DW_AT_element_list"); + // break; + + // case DW_AT_stmt_list: + // strcpy(attribName, "DW_AT_stmt_list"); + // break; + + // case DW_AT_low_pc: + // strcpy(attribName, "DW_AT_low_pc"); + // break; + + // case DW_AT_high_pc: + // strcpy(attribName, "DW_AT_high_pc"); + // break; + + // case DW_AT_language: + // strcpy(attribName, "DW_AT_language"); + // break; + + // case DW_AT_member: + // strcpy(attribName, "DW_AT_member"); + // break; + + // case DW_AT_discr: + // strcpy(attribName, "DW_AT_discr"); + // break; + + // case DW_AT_discr_value: + // strcpy(attribName, "DW_AT_discr_value"); + // break; + + // case DW_AT_visibility: + // strcpy(attribName, "DW_AT_visibility"); + // break; + + // case DW_AT_import: + // strcpy(attribName, "DW_AT_import"); + // break; + + // case DW_AT_string_length: + // strcpy(attribName, "DW_AT_string_length"); + // break; + + // case DW_AT_common_reference: + // strcpy(attribName, "DW_AT_common_reference"); + // break; + + // case DW_AT_comp_dir: + // strcpy(attribName, "DW_AT_comp_dir"); + // break; + + // case DW_AT_const_value: + // strcpy(attribName, "DW_AT_const_value"); + // break; + + // case DW_AT_containing_type: + // strcpy(attribName, "DW_AT_containing_type"); + // break; + + // case DW_AT_default_value: + // strcpy(attribName, "DW_AT_default_value"); + // break; - switch (attrNum) - { - case DW_AT_sibling: - strcpy(attribName, "DW_AT_sibling"); - break; + // case DW_AT_inline: + // strcpy(attribName, "DW_AT_inline"); + // break; - case DW_AT_location: - strcpy(attribName, "DW_AT_location"); - break; + // case DW_AT_is_optional: + // strcpy(attribName, "DW_AT_is_optional"); + // break; - case DW_AT_name: - strcpy(attribName, "DW_AT_name"); - break; + // case DW_AT_lower_bound: + // strcpy(attribName, "DW_AT_lower_bound"); + // break; - case DW_AT_ordering: - strcpy(attribName, "DW_AT_ordering"); - break; + // case DW_AT_producer: + // strcpy(attribName, "DW_AT_producer"); + // break; - case DW_AT_subscr_data: - strcpy(attribName, "DW_AT_subscr_data"); - break; + // case DW_AT_prototyped: + // strcpy(attribName, "DW_AT_prototyped"); + // break; - case DW_AT_byte_size: - strcpy(attribName, "DW_AT_byte_size"); - break; + // case DW_AT_return_addr: + // strcpy(attribName, "DW_AT_return_addr"); + // break; - case DW_AT_bit_offset: - strcpy(attribName, "DW_AT_bit_offset"); - break; + // case DW_AT_start_scope: + // strcpy(attribName, "DW_AT_start_scope"); + // break; - case DW_AT_bit_size: - strcpy(attribName, "DW_AT_bit_size"); - break; + // case DW_AT_bit_stride: + // strcpy(attribName, "DW_AT_bit_stride"); + // break; - case DW_AT_element_list: - strcpy(attribName, "DW_AT_element_list"); - break; + // case DW_AT_upper_bound: + // strcpy(attribName, "DW_AT_upper_bound"); + // break; - case DW_AT_stmt_list: - strcpy(attribName, "DW_AT_stmt_list"); - break; + // case DW_AT_abstract_origin: + // strcpy(attribName, "DW_AT_abstract_origin"); + // break; - case DW_AT_low_pc: - strcpy(attribName, "DW_AT_low_pc"); - break; + // case DW_AT_accessibility: + // strcpy(attribName, "DW_AT_accessibility"); + // break; - case DW_AT_high_pc: - strcpy(attribName, "DW_AT_high_pc"); - break; + // case DW_AT_address_class: + // strcpy(attribName, "DW_AT_address_class"); + // break; - case DW_AT_language: - strcpy(attribName, "DW_AT_language"); - break; + // case DW_AT_artificial: + // strcpy(attribName, "DW_AT_artificial"); + // break; - case DW_AT_member: - strcpy(attribName, "DW_AT_member"); - break; + // case DW_AT_base_types: + // strcpy(attribName, "DW_AT_base_types"); + // break; - case DW_AT_discr: - strcpy(attribName, "DW_AT_discr"); - break; + // case DW_AT_calling_convention: + // strcpy(attribName, "DW_AT_calling_convention"); + // break; - case DW_AT_discr_value: - strcpy(attribName, "DW_AT_discr_value"); - break; + // case DW_AT_count: + // strcpy(attribName, "DW_AT_count"); + // break; - case DW_AT_visibility: - strcpy(attribName, "DW_AT_visibility"); - break; + // case DW_AT_data_member_location: + // strcpy(attribName, "DW_AT_data_member_location"); + // break; - case DW_AT_import: - strcpy(attribName, "DW_AT_import"); - break; + // case DW_AT_decl_column: + // strcpy(attribName, "DW_AT_decl_column"); + // break; - case DW_AT_string_length: - strcpy(attribName, "DW_AT_string_length"); - break; + // case DW_AT_decl_file: + // strcpy(attribName, "DW_AT_decl_file"); + // break; - case DW_AT_common_reference: - strcpy(attribName, "DW_AT_common_reference"); - break; + // case DW_AT_decl_line: + // strcpy(attribName, "DW_AT_decl_line"); + // break; - case DW_AT_comp_dir: - strcpy(attribName, "DW_AT_comp_dir"); - break; + // case DW_AT_declaration: + // strcpy(attribName, "DW_AT_declaration"); + // break; - case DW_AT_const_value: - strcpy(attribName, "DW_AT_const_value"); - break; + // case DW_AT_discr_list: + // strcpy(attribName, "DW_AT_discr_list"); + // break; - case DW_AT_containing_type: - strcpy(attribName, "DW_AT_containing_type"); - break; + // case DW_AT_encoding: + // strcpy(attribName, "DW_AT_encoding"); + // break; - case DW_AT_default_value: - strcpy(attribName, "DW_AT_default_value"); - break; + // case DW_AT_external: + // strcpy(attribName, "DW_AT_external"); + // break; - case DW_AT_inline: - strcpy(attribName, "DW_AT_inline"); - break; + // case DW_AT_frame_base: + // strcpy(attribName, "DW_AT_frame_base"); + // break; - case DW_AT_is_optional: - strcpy(attribName, "DW_AT_is_optional"); - break; + // case DW_AT_friend: + // strcpy(attribName, "DW_AT_friend"); + // break; - case DW_AT_lower_bound: - strcpy(attribName, "DW_AT_lower_bound"); - break; + // case DW_AT_identifier_case: + // strcpy(attribName, "DW_AT_identifier_case"); + // break; - case DW_AT_producer: - strcpy(attribName, "DW_AT_producer"); - break; + // case DW_AT_macro_info: + // strcpy(attribName, "DW_AT_macro_info"); + // printf("DW_AT_macro_info************************\n"); + // break; - case DW_AT_prototyped: - strcpy(attribName, "DW_AT_prototyped"); - break; + // case DW_AT_namelist_item: + // strcpy(attribName, "DW_AT_namelist_item"); + // break; - case DW_AT_return_addr: - strcpy(attribName, "DW_AT_return_addr"); - break; + // case DW_AT_priority: + // strcpy(attribName, "DW_AT_priority"); + // break; - case DW_AT_start_scope: - strcpy(attribName, "DW_AT_start_scope"); - break; + // case DW_AT_segment: + // strcpy(attribName, "DW_AT_segment"); + // break; - case DW_AT_bit_stride: - strcpy(attribName, "DW_AT_bit_stride"); - break; + // case DW_AT_specification: + // strcpy(attribName, "DW_AT_specification"); + // break; - case DW_AT_upper_bound: - strcpy(attribName, "DW_AT_upper_bound"); - break; + // case DW_AT_static_link: + // strcpy(attribName, "DW_AT_static_link"); + // break; - case DW_AT_abstract_origin: - strcpy(attribName, "DW_AT_abstract_origin"); - break; + // case DW_AT_type: + // strcpy(attribName, "DW_AT_type"); + // break; - case DW_AT_accessibility: - strcpy(attribName, "DW_AT_accessibility"); - break; + // case DW_AT_use_location: + // strcpy(attribName, "DW_AT_use_location"); + // break; - case DW_AT_address_class: - strcpy(attribName, "DW_AT_address_class"); - break; + // case DW_AT_variable_parameter: + // strcpy(attribName, "DW_AT_variable_parameter"); + // break; - case DW_AT_artificial: - strcpy(attribName, "DW_AT_artificial"); - break; + // case DW_AT_virtuality: + // strcpy(attribName, "DW_AT_virtuality"); + // break; - case DW_AT_base_types: - strcpy(attribName, "DW_AT_base_types"); - break; + // case DW_AT_vtable_elem_location: + // strcpy(attribName, "DW_AT_vtable_elem_location"); + // break; - case DW_AT_calling_convention: - strcpy(attribName, "DW_AT_calling_convention"); - break; + // case DW_AT_allocated: + // strcpy(attribName, "DW_AT_allocated"); + // break; - case DW_AT_count: - strcpy(attribName, "DW_AT_count"); - break; + // case DW_AT_associated: + // strcpy(attribName, "DW_AT_associated"); + // break; - case DW_AT_data_member_location: - strcpy(attribName, "DW_AT_data_member_location"); - break; + // case DW_AT_data_location: + // strcpy(attribName, "DW_AT_data_location"); + // break; - case DW_AT_decl_column: - strcpy(attribName, "DW_AT_decl_column"); - break; + // case DW_AT_byte_stride: + // strcpy(attribName, "DW_AT_byte_stride"); + // break; - case DW_AT_decl_file: - strcpy(attribName, "DW_AT_decl_file"); - break; + // case DW_AT_entry_pc: + // strcpy(attribName, "DW_AT_entry_pc"); + // break; - case DW_AT_decl_line: - strcpy(attribName, "DW_AT_decl_line"); - break; + // case DW_AT_use_UTF8: + // strcpy(attribName, "DW_AT_use_UTF8"); + // break; - case DW_AT_declaration: - strcpy(attribName, "DW_AT_declaration"); - break; + // case DW_AT_extension: + // strcpy(attribName, "DW_AT_extension"); + // break; - case DW_AT_discr_list: - strcpy(attribName, "DW_AT_discr_list"); - break; - - case DW_AT_encoding: - strcpy(attribName, "DW_AT_encoding"); - break; - - case DW_AT_external: - strcpy(attribName, "DW_AT_external"); - break; - - case DW_AT_frame_base: - strcpy(attribName, "DW_AT_frame_base"); - break; - - case DW_AT_friend: - strcpy(attribName, "DW_AT_friend"); - break; - - case DW_AT_identifier_case: - strcpy(attribName, "DW_AT_identifier_case"); - break; - - case DW_AT_macro_info: - strcpy(attribName, "DW_AT_macro_info"); - printf("DW_AT_macro_info************************\n"); - break; - - case DW_AT_namelist_item: - strcpy(attribName, "DW_AT_namelist_item"); - break; - - case DW_AT_priority: - strcpy(attribName, "DW_AT_priority"); - break; - - case DW_AT_segment: - strcpy(attribName, "DW_AT_segment"); - break; - - case DW_AT_specification: - strcpy(attribName, "DW_AT_specification"); - break; - - case DW_AT_static_link: - strcpy(attribName, "DW_AT_static_link"); - break; - - case DW_AT_type: - strcpy(attribName, "DW_AT_type"); - break; - - case DW_AT_use_location: - strcpy(attribName, "DW_AT_use_location"); - break; - - case DW_AT_variable_parameter: - strcpy(attribName, "DW_AT_variable_parameter"); - break; - - case DW_AT_virtuality: - strcpy(attribName, "DW_AT_virtuality"); - break; - - case DW_AT_vtable_elem_location: - strcpy(attribName, "DW_AT_vtable_elem_location"); - break; - - case DW_AT_allocated: - strcpy(attribName, "DW_AT_allocated"); - break; - - case DW_AT_associated: - strcpy(attribName, "DW_AT_associated"); - break; - - case DW_AT_data_location: - strcpy(attribName, "DW_AT_data_location"); - break; - - case DW_AT_byte_stride: - strcpy(attribName, "DW_AT_byte_stride"); - break; - - case DW_AT_entry_pc: - strcpy(attribName, "DW_AT_entry_pc"); - break; - - case DW_AT_use_UTF8: - strcpy(attribName, "DW_AT_use_UTF8"); - break; - - case DW_AT_extension: - strcpy(attribName, "DW_AT_extension"); - break; - - case DW_AT_ranges: - strcpy(attribName, "DW_AT_ranges"); - break; - - case DW_AT_trampoline: - strcpy(attribName, "DW_AT_trampoline"); - break; - - case DW_AT_call_column: - strcpy(attribName, "DW_AT_call_column"); - break; - - case DW_AT_call_file: - strcpy(attribName, "DW_AT_call_file"); - break; - - case DW_AT_call_line: - strcpy(attribName, "DW_AT_call_line"); - break; - - case DW_AT_description: - strcpy(attribName, "DW_AT_description"); - break; - - case DW_AT_binary_scale: - strcpy(attribName, "DW_AT_binary_scale"); - break; - - case DW_AT_decimal_scale: - strcpy(attribName, "DW_AT_decimal_scale"); - break; - - case DW_AT_small: - strcpy(attribName, "DW_AT_small"); - break; - - case DW_AT_decimal_sign: - strcpy(attribName, "DW_AT_decimal_sign"); - break; - - case DW_AT_digit_count: - strcpy(attribName, "DW_AT_digit_count"); - break; - - case DW_AT_picture_string: - strcpy(attribName, "DW_AT_picture_string"); - break; - - case DW_AT_mutable: - strcpy(attribName, "DW_AT_mutable"); - break; - - case DW_AT_threads_scaled: - strcpy(attribName, "DW_AT_threads_scaled"); - break; - - case DW_AT_explicit: - strcpy(attribName, "DW_AT_explicit"); - break; - - case DW_AT_object_pointer: - strcpy(attribName, "DW_AT_object_pointer"); - break; - - case DW_AT_endianity: - strcpy(attribName, "DW_AT_endianity"); - break; - - case DW_AT_elemental: - strcpy(attribName, "DW_AT_elemental"); - break; - - case DW_AT_pure: - strcpy(attribName, "DW_AT_pure"); - break; - - case DW_AT_recursive: - strcpy(attribName, "DW_AT_recursive"); - break; - - case DW_AT_signature: - strcpy(attribName, "DW_AT_signature"); - break; - - case DW_AT_main_subprogram: - strcpy(attribName, "DW_AT_main_subprogram"); - break; - - case DW_AT_data_bit_offset: - strcpy(attribName, "DW_AT_data_bit_offset"); - break; - - case DW_AT_const_expr: - strcpy(attribName, "DW_AT_const_expr"); - break; - - case DW_AT_enum_class: - strcpy(attribName, "DW_AT_enum_class"); - break; - - case DW_AT_linkage_name: - strcpy(attribName, "DW_AT_linkage_name"); - break; - - case DW_AT_string_length_bit_size: - strcpy(attribName, "DW_AT_string_length_bit_size"); - break; - - case DW_AT_string_length_byte_size: - strcpy(attribName, "DW_AT_string_length_byte_size"); - break; - - case DW_AT_rank: - strcpy(attribName, "DW_AT_rank"); - break; - - case DW_AT_str_offsets_base: - strcpy(attribName, "DW_AT_str_offsets_base"); - break; - - case DW_AT_addr_base: - strcpy(attribName, "DW_AT_addr_base"); - break; - - case DW_AT_rnglists_base: - strcpy(attribName, "DW_AT_rnglists_base"); - break; - - case DW_AT_dwo_id: - strcpy(attribName, "DW_AT_dwo_id"); - break; - - case DW_AT_dwo_name: - strcpy(attribName, "DW_AT_dwo_name"); - break; - - case DW_AT_reference: - strcpy(attribName, "DW_AT_reference"); - break; - - case DW_AT_rvalue_reference: - strcpy(attribName, "DW_AT_rvalue_reference"); - break; - - case DW_AT_macros: - strcpy(attribName, "DW_AT_macros"); - printf("DW_AT_macros\n"); - break; - - case DW_AT_call_all_calls: - strcpy(attribName, "DW_AT_call_all_calls"); - break; - - case DW_AT_call_all_source_calls: - strcpy(attribName, "DW_AT_call_all_source_calls"); - break; - - case DW_AT_call_all_tail_calls: - strcpy(attribName, "DW_AT_call_all_tail_calls"); - break; - - case DW_AT_call_return_pc: - strcpy(attribName, "DW_AT_call_return_pc"); - break; - - case DW_AT_call_value: - strcpy(attribName, "DW_AT_call_value"); - break; - - case DW_AT_call_origin: - strcpy(attribName, "DW_AT_call_origin"); - break; - - case DW_AT_call_parameter: - strcpy(attribName, "DW_AT_call_parameter"); - break; - - case DW_AT_call_pc: - strcpy(attribName, "DW_AT_call_pc"); - break; - - case DW_AT_call_tail_call: - strcpy(attribName, "DW_AT_call_tail_call"); - break; - - case DW_AT_call_target: - strcpy(attribName, "DW_AT_call_target"); - break; - - case DW_AT_call_target_clobbered: - strcpy(attribName, "DW_AT_call_target_clobbered"); - break; - - case DW_AT_call_data_location: - strcpy(attribName, "DW_AT_call_data_location"); - break; - - case DW_AT_call_data_value: - strcpy(attribName, "DW_AT_call_data_value"); - break; - - case DW_AT_noreturn: - strcpy(attribName, "DW_AT_noreturn"); - break; - - case DW_AT_alignment: - strcpy(attribName, "DW_AT_alignment"); - break; - - case DW_AT_export_symbols: - strcpy(attribName, "DW_AT_export_symbols"); - break; - - case DW_AT_deleted: - strcpy(attribName, "DW_AT_deleted"); - break; - - case DW_AT_defaulted: - strcpy(attribName, "DW_AT_defaulted"); - break; - - case DW_AT_loclists_base: - strcpy(attribName, "DW_AT_loclists_base"); - break; - - default: - sprintf(attribName, "UNKNOWN (%x)", attrNum); - break; - } - - res = dwarf_whatform(attribs[i], &attrNum, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_whatattr. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); - } - else - { - res = dwarf_whatform(attribs[i], &formID, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_whatform. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); - } - else - { - switch (formID) - { - case DW_FORM_addr: - { - Dwarf_Addr addr = 0; - - strcpy(formName, "DW_FORM_addr"); - - res = dwarf_formaddr(attribs[i], &addr, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in DW_FORM_addr. line=%u errno=%u %s", __LINE__, dwarf_errno(error), dwarf_errmsg(error)); - } - else - { - unsigned long long data = (unsigned int)addr; - sprintf(value, "0x%016x", data); - } - - break; - } - - case DW_FORM_block2: - { - Dwarf_Unsigned udata = 0; - - strcpy(formName, "DW_FORM_block2"); - - res = dwarf_formudata(attribs[i], &udata, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - dwarf_errmsg(error)); - } - else - { - unsigned short data = (unsigned short)udata; - sprintf(value, "%d", data); - } - - break; - } - - case DW_FORM_block4: - { - Dwarf_Unsigned udata = 0; - - strcpy(formName, "DW_FORM_block4"); - - res = dwarf_formudata(attribs[i], &udata, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in DW_FORM_block4. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - dwarf_errmsg(error)); - } - else - { - unsigned int data = (unsigned int)udata; - sprintf(value, "%d", data); - } - - break; - } - - case DW_FORM_data2: - { - Dwarf_Unsigned udata = 0; - - strcpy(formName, "DW_FORM_data2"); - - res = dwarf_formudata(attribs[i], &udata, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in DW_FORM_data2. line=%u errno=%u %s", __LINE__, dwarf_errno(error), dwarf_errmsg(error)); - } - else - { - unsigned short int data = (unsigned short int)udata; - sprintf(value, "%d", data); - } - - break; - } - - case DW_FORM_data4: - { - Dwarf_Unsigned udata = 0; - - strcpy(formName, "DW_FORM_data4"); - res = dwarf_formudata(attribs[i], &udata, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - dwarf_errmsg(error)); - } - else - { - unsigned int data = (unsigned int)udata; - sprintf(value, "%d", data); - } - - break; - } - - case DW_FORM_data8: - { - Dwarf_Unsigned udata = 0; - - strcpy(formName, "DW_FORM_data8"); - - res = dwarf_formudata(attribs[i], &udata, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - dwarf_errmsg(error)); - } - else - { - sprintf(value, "%d", udata); - } - - break; - } - - case DW_FORM_string: - { - char *str = 0; - - strcpy(formName, "DW_FORM_string"); - - res = dwarf_formstring(attribs[i], &str, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_formstring. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); - } - else - { - sprintf(value, "%s", str); - } - - break; - } - - case DW_FORM_block: - strcpy(formName, "DW_FORM_block"); - break; - - case DW_FORM_block1: - { - Dwarf_Block *bdata = 0; - strcpy(formName, "DW_FORM_block1"); - - res = dwarf_formblock(attribs[i], &bdata, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_formblock. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - dwarf_errmsg(error)); - } - else - { - sprintf(value, "len: %d", bdata->bl_len); - } - - break; - } - - case DW_FORM_data1: - { - Dwarf_Unsigned udata = 0; - strcpy(formName, "DW_FORM_data1"); - - res = dwarf_formudata(attribs[i], &udata, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - dwarf_errmsg(error)); - } - else - { - uint8_t data = (uint8_t)udata; - sprintf(value, "%u", data); - } - - break; - } - - case DW_FORM_flag: - { - Dwarf_Bool dwarfBool = false; - strcpy(formName, "DW_FORM_flag"); - char *strp = 0; - - res = dwarf_formflag(attribs[i], &dwarfBool, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in DW_FORM_flag. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); - } - else - { - if (dwarfBool) - { - sprintf(value, "TRUE"); - } - else - { - sprintf(value, "FALSE"); - } - } - - break; - } - - case DW_FORM_sdata: - { - Dwarf_Signed sdata = 0; - - strcpy(formName, "DW_FORM_sdata"); - - res = dwarf_formsdata(attribs[i], &sdata, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - dwarf_errmsg(error)); - } - else - { - sprintf(value, "%lli", sdata); - } - - break; - } - - case DW_FORM_strp: - { - char *strp = 0; - - strcpy(formName, "DW_FORM_strp"); - - res = dwarf_formstring(attribs[i], &strp, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_formstring. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); - } - else - { - char *text = dwarfStringToChar(strp); - sprintf(value, "%s", text); - } - - break; - } - - case DW_FORM_udata: - { - Dwarf_Unsigned udata = 0; - - strcpy(formName, "DW_FORM_udata"); - - res = dwarf_formudata(attribs[i], &udata, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - dwarf_errmsg(error)); - } - else - { - sprintf(value, "%llu", udata); - } - - break; - } - - case DW_FORM_ref_addr: - strcpy(formName, "DW_FORM_ref_addr"); - break; - - case DW_FORM_ref1: - { - Dwarf_Off ref = 0; - - strcpy(formName, "DW_FORM_ref1"); - res = dwarf_formref(attribs[i], &ref, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - dwarf_errmsg(error)); - } - else - { - uint8_t data = (uint8_t)ref; - sprintf(value, "%u", data); - } - - break; - } - - case DW_FORM_ref2: - { - Dwarf_Off ref = 0; - - strcpy(formName, "DW_FORM_ref1"); - res = dwarf_formref(attribs[i], &ref, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - dwarf_errmsg(error)); - } - else - { - unsigned short int data = (unsigned short int)ref; - sprintf(value, "%u", data); - } - - break; - } - - case DW_FORM_ref4: - { - Dwarf_Off ref = 0; - - strcpy(formName, "DW_FORM_ref1"); - res = dwarf_formref(attribs[i], &ref, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - dwarf_errmsg(error)); - } - else - { - unsigned int data = (unsigned int)ref; - sprintf(value, "%u", data); - } - - break; - } - - case DW_FORM_ref8: - { - Dwarf_Off ref = 0; - - strcpy(formName, "DW_FORM_ref1"); - res = dwarf_formref(attribs[i], &ref, &error); - if (res != DW_DLV_OK) - { - logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - dwarf_errmsg(error)); - } - else - { - sprintf(value, "%llu", ref); - } + // case DW_AT_ranges: + // strcpy(attribName, "DW_AT_ranges"); + // break; - break; - } + // case DW_AT_trampoline: + // strcpy(attribName, "DW_AT_trampoline"); + // break; - case DW_FORM_ref_udata: - strcpy(formName, "DW_FORM_ref_udata"); - break; + // case DW_AT_call_column: + // strcpy(attribName, "DW_AT_call_column"); + // break; - case DW_FORM_indirect: - strcpy(formName, "DW_FORM_indirect"); - break; + // case DW_AT_call_file: + // strcpy(attribName, "DW_AT_call_file"); + // break; - case DW_FORM_sec_offset: - strcpy(formName, "DW_FORM_sec_offset"); - break; + // case DW_AT_call_line: + // strcpy(attribName, "DW_AT_call_line"); + // break; - case DW_FORM_exprloc: - strcpy(formName, "DW_FORM_exprloc"); - break; + // case DW_AT_description: + // strcpy(attribName, "DW_AT_description"); + // break; - case DW_FORM_flag_present: - strcpy(formName, "DW_FORM_flag_present"); - break; + // case DW_AT_binary_scale: + // strcpy(attribName, "DW_AT_binary_scale"); + // break; - case DW_FORM_strx: - strcpy(formName, "DW_FORM_strx"); - break; + // case DW_AT_decimal_scale: + // strcpy(attribName, "DW_AT_decimal_scale"); + // break; - case DW_FORM_addrx: - strcpy(formName, "DW_FORM_addrx"); - break; + // case DW_AT_small: + // strcpy(attribName, "DW_AT_small"); + // break; - case DW_FORM_ref_sup4: - strcpy(formName, "DW_FORM_ref_sup4"); - break; + // case DW_AT_decimal_sign: + // strcpy(attribName, "DW_AT_decimal_sign"); + // break; - case DW_FORM_strp_sup: - strcpy(formName, "DW_FORM_strp_sup"); - break; + // case DW_AT_digit_count: + // strcpy(attribName, "DW_AT_digit_count"); + // break; - case DW_FORM_data16: - strcpy(formName, "DW_FORM_data16"); - break; + // case DW_AT_picture_string: + // strcpy(attribName, "DW_AT_picture_string"); + // break; - case DW_FORM_line_strp: - strcpy(formName, "DW_FORM_line_strp"); - break; + // case DW_AT_mutable: + // strcpy(attribName, "DW_AT_mutable"); + // break; - case DW_FORM_ref_sig8: - strcpy(formName, "DW_FORM_ref_sig8"); - break; + // case DW_AT_threads_scaled: + // strcpy(attribName, "DW_AT_threads_scaled"); + // break; - case DW_FORM_implicit_const: - strcpy(formName, "DW_FORM_implicit_const"); - break; + // case DW_AT_explicit: + // strcpy(attribName, "DW_AT_explicit"); + // break; - case DW_FORM_loclistx: - strcpy(formName, "DW_FORM_loclistx"); - break; + // case DW_AT_object_pointer: + // strcpy(attribName, "DW_AT_object_pointer"); + // break; - case DW_FORM_rnglistx: - strcpy(formName, "DW_FORM_rnglistx"); - break; + // case DW_AT_endianity: + // strcpy(attribName, "DW_AT_endianity"); + // break; - case DW_FORM_ref_sup8: - strcpy(formName, "DW_FORM_ref_sup8"); - break; + // case DW_AT_elemental: + // strcpy(attribName, "DW_AT_elemental"); + // break; - case DW_FORM_strx1: - strcpy(formName, "DW_FORM_strx1"); - break; + // case DW_AT_pure: + // strcpy(attribName, "DW_AT_pure"); + // break; - case DW_FORM_strx2: - strcpy(formName, "DW_FORM_strx2"); - break; + // case DW_AT_recursive: + // strcpy(attribName, "DW_AT_recursive"); + // break; - case DW_FORM_strx3: - strcpy(formName, "DW_FORM_strx3"); - break; + // case DW_AT_signature: + // strcpy(attribName, "DW_AT_signature"); + // break; - case DW_FORM_strx4: - strcpy(formName, "DW_FORM_strx4"); - break; + // case DW_AT_main_subprogram: + // strcpy(attribName, "DW_AT_main_subprogram"); + // break; - case DW_FORM_addrx1: - strcpy(formName, "DW_FORM_addrx1"); - break; + // case DW_AT_data_bit_offset: + // strcpy(attribName, "DW_AT_data_bit_offset"); + // break; - case DW_FORM_addrx2: - strcpy(formName, "DW_FORM_addrx2"); - break; + // case DW_AT_const_expr: + // strcpy(attribName, "DW_AT_const_expr"); + // break; - case DW_FORM_addrx3: - strcpy(formName, "DW_FORM_addrx3"); - break; + // case DW_AT_enum_class: + // strcpy(attribName, "DW_AT_enum_class"); + // break; - case DW_FORM_addrx4: - strcpy(formName, "DW_FORM_addrx4"); - break; + // case DW_AT_linkage_name: + // strcpy(attribName, "DW_AT_linkage_name"); + // break; - case DW_FORM_GNU_addr_index: - strcpy(formName, "DW_FORM_GNU_addr_index"); - break; + // case DW_AT_string_length_bit_size: + // strcpy(attribName, "DW_AT_string_length_bit_size"); + // break; - case DW_FORM_GNU_str_index: - strcpy(formName, "DW_FORM_GNU_str_index"); - break; + // case DW_AT_string_length_byte_size: + // strcpy(attribName, "DW_AT_string_length_byte_size"); + // break; - case DW_FORM_GNU_ref_alt: - strcpy(formName, "DW_FORM_GNU_ref_alt"); - break; + // case DW_AT_rank: + // strcpy(attribName, "DW_AT_rank"); + // break; - case DW_FORM_GNU_strp_alt: - strcpy(formName, "DW_FORM_GNU_strp_alt"); - break; + // case DW_AT_str_offsets_base: + // strcpy(attribName, "DW_AT_str_offsets_base"); + // break; - default: - sprintf(formName, "UNKNOWN (%x)", formID); - break; - } - } - } - } + // case DW_AT_addr_base: + // strcpy(attribName, "DW_AT_addr_base"); + // break; - sprintf(line, " %-20s : %-20s (%s)\n", attribName, value, formName); - strcat(output, line); - } - } - } + // case DW_AT_rnglists_base: + // strcpy(attribName, "DW_AT_rnglists_base"); + // break; - // res = dwarf_attr(inDie, DW_AT_name, &attr_struct, &error); - // if(res == DW_DLV_OK) - // { - // res = dwarf_formstring(attr_struct, &dieName, &error); - // if(res != DW_DLV_OK) - // { - // logger.logError("Error in dwarf_formstring. errno=%u %s", dwarf_errno(error), - // dwarf_errmsg(error)); - // } - // else - // { - // sprintf(line, " DW_AT_name : %s", dieName); - // strcpy(output, line); - // } - // } - // - // res = dwarf_die_abbrev_children_flag(inDie, &hasChildrenFlag); - // if(res != DW_DLV_OK) - // { - // logger.logError("Error in dwarf_die_abbrev_children_flag. errno=%u %s", dwarf_errno(error), - // dwarf_errmsg(error)); - // } - - // else - // { - // logger.logDebug(" Has children: %s", hasChildrenFlag ? "True" : "False"); - // } - // - // int dwarf_die_abbrev_children_flag(Dwarf_Die /*die*/, - // Dwarf_Half * /*ab_has_child*/); - // - // res = dwarf_attrlist(inDie, &attribs, &attribCount, &error); - // if(res != DW_DLV_OK) - // { - // logger.logError("Error in dwarf_attrlist. errno=%u %s", dwarf_errno(error), - // dwarf_errmsg(error)); - // } - // else - // { - // if(attribCount > 0) - // { - // logger.logDebug(" Attributes:"); - // for(uint32_t i = 0; i < attribCount; ++i) - // { - // Dwarf_Half attrNum; - // res = dwarf_whatattr(attribs[i], &attrNum, &error); - // if(res != DW_DLV_OK) - // { - // logger.logError("Error in dwarf_whatattr. errno=%u %s", dwarf_errno(error), - // dwarf_errmsg(error)); - // } - // else - // { - // Dwarf_Half formID; - // - // switch(attrNum) - // { - // case DW_AT_sibling: - // logger.logDebug(" DW_AT_sibling"); - // break; - // - // case DW_AT_location: - // logger.logDebug(" DW_AT_location"); - // break; - // - // case DW_AT_name: - // logger.logDebug(" DW_AT_name"); - // break; - // - // case DW_AT_ordering: - // logger.logDebug(" DW_AT_ordering"); - // break; - // - // case DW_AT_subscr_data: - // logger.logDebug(" DW_AT_subscr_data"); - // break; - // - // case DW_AT_byte_size: - // logger.logDebug(" DW_AT_byte_size"); - // break; - // - // case DW_AT_decl_file: - // logger.logDebug(" DW_AT_decl_file"); - // break; - // - // case DW_AT_decl_line: - // logger.logDebug(" DW_AT_decl_line"); - // break; - // - // case DW_AT_type: - // logger.logDebug(" DW_AT_type"); - // break; - // - // default: - // logger.logDebug(" 0x%02x", attrNum); - // break; - // } - // - // res = dwarf_whatform(attribs[i], &attrNum, &error); - // if(res != DW_DLV_OK) - // { - // logger.logError("Error in dwarf_whatattr. errno=%u %s", dwarf_errno(error), - // dwarf_errmsg(error)); - // } - // else - // { - // res = dwarf_whatform(attribs[i], &formID, &error); - // if(res != DW_DLV_OK) - // { - // logger.logError("Error in dwarf_whatform. errno=%u %s", dwarf_errno(error), - // dwarf_errmsg(error)); - // } - // else - // { - // switch(formID) - // { - // case DW_FORM_addr: - // logger.logDebug(":DW_FORM_addr"); - // break; - // - // case DW_FORM_block2: - // logger.logDebug(":DW_FORM_block2"); - // break; - // - // case DW_FORM_block4: - // logger.logDebug(":DW_FORM_block4"); - // break; - // - // case DW_FORM_data1: - // { - // Dwarf_Unsigned udata = 0; - // res = dwarf_formudata(attribs[i], &udata, &error); - // if(res != DW_DLV_OK) - // { - // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - // dwarf_errmsg(error)); - // } - // else - // { - // char data = (char) udata; - // logger.logDebug(":DW_FORM_data1:%u", data); - // } - // break; - // } - // - // case DW_FORM_data2: - // { - // Dwarf_Unsigned udata = 0; - // res = dwarf_formudata(attribs[i], &udata, &error); - // if(res != DW_DLV_OK) - // { - // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - // dwarf_errmsg(error)); - // } - // else - // { - // unsigned short data = (unsigned short) udata; - // logger.logDebug(":DW_FORM_data2:%u", data); - // } - // break; - // } - // - // case DW_FORM_data4: - // { - // Dwarf_Unsigned udata = 0; - // res = dwarf_formudata(attribs[i], &udata, &error); - // if(res != DW_DLV_OK) - // { - // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - // dwarf_errmsg(error)); - // } - // else - // { - // unsigned int data = (unsigned int) udata; - // logger.logDebug(":DW_FORM_data4:%u", data); - // } - // break; - // } - // - // case DW_FORM_data8: - // { - // Dwarf_Unsigned udata = 0; - // res = dwarf_formudata(attribs[i], &udata, &error); - // if(res != DW_DLV_OK) - // { - // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - // dwarf_errmsg(error)); - // } - // else - // { - // logger.logDebug(":DW_FORM_data8:%llu", udata); - // } - // break; - // } - // - // case DW_FORM_string: - // { - // char *str = 0; - // res = dwarf_formstring(attribs[i], &str, &error); - // if(res != DW_DLV_OK) - // { - // logger.logError("Error in dwarf_formstring. errno=%u %s", dwarf_errno(error), - // dwarf_errmsg(error)); - // } - // else - // { - // logger.logDebug(":DW_FORM_string:%s", str); - // } - // break; - // } - // - // case DW_FORM_block: - // logger.logDebug(":DW_FORM_block"); - // break; - // - // case DW_FORM_sdata: - // logger.logDebug(":DW_FORM_sdata"); - // break; - // - // case DW_FORM_strp: - // { - // char *strp = 0; - // res = dwarf_formstring(attribs[i], &strp, &error); - // if(res != DW_DLV_OK) - // { - // logger.logError("Error in dwarf_formstring. errno=%u %s", dwarf_errno(error), - // dwarf_errmsg(error)); - // } - // else - // { - // char *text = dwarfStringToChar(strp); - // logger.logDebug(":DW_FORM_strp:%s", text); - // } - // break; - // } - // - // case DW_FORM_udata: - // { - // Dwarf_Unsigned udata = 0; - // res = dwarf_formudata(attribs[i], &udata, &error); - // if(res != DW_DLV_OK) - // { - // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - // dwarf_errmsg(error)); - // } - // else - // { - // logger.logDebug(":DW_FORM_udata:%llu", udata); - // } - // break; - // } - // - // case DW_FORM_ref_addr: - // logger.logDebug(":DW_FORM_ref_addr"); - // break; - // - // case DW_FORM_ref1: - // { - // Dwarf_Off ref = 0; - // res = dwarf_formref(attribs[i], &ref, &error); - // if(res != DW_DLV_OK) - // { - // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), - // dwarf_errmsg(error)); - // } - // else - // { - // char data = (char) ref; - // logger.logDebug(":DW_FORM_ref1:%u", data); - // } - // break; - // } - // - // case DW_FORM_ref2: - // { - // Dwarf_Off ref = 0; - // res = dwarf_formref(attribs[i], &ref, &error); - // if(res != DW_DLV_OK) - // { - // logger.logError("Error in dwarf_formref. errno=%u %s", dwarf_errno(error), - // dwarf_errmsg(error)); - // } - // else - // { - // unsigned short int data = (unsigned short int) ref; - // logger.logDebug(":DW_FORM_ref2:%u", data); - // } - // break; - // } - // - // case DW_FORM_ref4: - // { - // Dwarf_Off ref = 0; - // res = dwarf_formref(attribs[i], &ref, &error); - // if(res != DW_DLV_OK) - // { - // logger.logError("Error in dwarf_formref. errno=%u %s", dwarf_errno(error), - // dwarf_errmsg(error)); - // } - // else - // { - // unsigned int data = (unsigned int) ref; - // logger.logDebug(":DW_FORM_ref4:%u", data); - // } - // break; - // } - // - // case DW_FORM_ref8: - // { - // Dwarf_Off ref = 0; - // res = dwarf_formref(attribs[i], &ref, &error); - // if(res != DW_DLV_OK) - // { - // logger.logError("Error in dwarf_formref. errno=%u %s", dwarf_errno(error), - // dwarf_errmsg(error)); - // } - // else - // { - // logger.logDebug(":DW_FORM_ref4:%llu", ref); - // } - // break; - // } - // - // case DW_FORM_ref_udata: - // logger.logDebug(":DW_FORM_ref_udata"); - // break; - // - // case DW_FORM_indirect: - // logger.logDebug(":DW_FORM_indirect"); - // break; - // - // case DW_FORM_sec_offset: - // logger.logDebug(":DW_FORM_sec_offset"); - // break; - // - // case DW_FORM_exprloc: - // logger.logDebug(":DW_FORM_exprloc"); - // break; - // - // case DW_FORM_flag_present: - // logger.logDebug(":DW_FORM_flag_present"); - // break; - // - // case DW_FORM_ref_sig8: - // logger.logDebug(":DW_FORM_ref_sig8"); - // break; - // - // default: - // logger.logDebug(":0x%02x", formID); - // break; - // - // } - // } - // } - // } - // } - // logger.logDebug("\n"); - // } - // } - - logger.logDebug(output); - } + // case DW_AT_dwo_id: + // strcpy(attribName, "DW_AT_dwo_id"); + // break; + + // case DW_AT_dwo_name: + // strcpy(attribName, "DW_AT_dwo_name"); + // break; + + // case DW_AT_reference: + // strcpy(attribName, "DW_AT_reference"); + // break; + + // case DW_AT_rvalue_reference: + // strcpy(attribName, "DW_AT_rvalue_reference"); + // break; + + // case DW_AT_macros: + // strcpy(attribName, "DW_AT_macros"); + // printf("DW_AT_macros\n"); + // break; + + // case DW_AT_call_all_calls: + // strcpy(attribName, "DW_AT_call_all_calls"); + // break; + + // case DW_AT_call_all_source_calls: + // strcpy(attribName, "DW_AT_call_all_source_calls"); + // break; + + // case DW_AT_call_all_tail_calls: + // strcpy(attribName, "DW_AT_call_all_tail_calls"); + // break; + + // case DW_AT_call_return_pc: + // strcpy(attribName, "DW_AT_call_return_pc"); + // break; + + // case DW_AT_call_value: + // strcpy(attribName, "DW_AT_call_value"); + // break; + + // case DW_AT_call_origin: + // strcpy(attribName, "DW_AT_call_origin"); + // break; + + // case DW_AT_call_parameter: + // strcpy(attribName, "DW_AT_call_parameter"); + // break; + + // case DW_AT_call_pc: + // strcpy(attribName, "DW_AT_call_pc"); + // break; + + // case DW_AT_call_tail_call: + // strcpy(attribName, "DW_AT_call_tail_call"); + // break; + + // case DW_AT_call_target: + // strcpy(attribName, "DW_AT_call_target"); + // break; + + // case DW_AT_call_target_clobbered: + // strcpy(attribName, "DW_AT_call_target_clobbered"); + // break; + + // case DW_AT_call_data_location: + // strcpy(attribName, "DW_AT_call_data_location"); + // break; + + // case DW_AT_call_data_value: + // strcpy(attribName, "DW_AT_call_data_value"); + // break; + + // case DW_AT_noreturn: + // strcpy(attribName, "DW_AT_noreturn"); + // break; + + // case DW_AT_alignment: + // strcpy(attribName, "DW_AT_alignment"); + // break; + + // case DW_AT_export_symbols: + // strcpy(attribName, "DW_AT_export_symbols"); + // break; + + // case DW_AT_deleted: + // strcpy(attribName, "DW_AT_deleted"); + // break; + + // case DW_AT_defaulted: + // strcpy(attribName, "DW_AT_defaulted"); + // break; + + // case DW_AT_loclists_base: + // strcpy(attribName, "DW_AT_loclists_base"); + // break; + + // default: + // sprintf(attribName, "UNKNOWN (%x)", attrNum); + // break; + // } + + // res = dwarf_whatform(attribs[i], &attrNum, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_whatattr. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); + // } + // else + // { + // res = dwarf_whatform(attribs[i], &formID, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_whatform. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); + // } + // else + // { + // switch (formID) + // { + // case DW_FORM_addr: + // { + // Dwarf_Addr addr = 0; + + // strcpy(formName, "DW_FORM_addr"); + + // res = dwarf_formaddr(attribs[i], &addr, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in DW_FORM_addr. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // dwarf_errmsg(error)); + // } + // else + // { + // unsigned long long data = (unsigned int)addr; + // sprintf(value, "0x%016x", data); + // } + + // break; + // } + + // case DW_FORM_block2: + // { + // Dwarf_Unsigned udata = 0; + + // strcpy(formName, "DW_FORM_block2"); + + // res = dwarf_formudata(attribs[i], &udata, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // dwarf_errmsg(error)); + // } + // else + // { + // unsigned short data = (unsigned short)udata; + // sprintf(value, "%d", data); + // } + + // break; + // } + + // case DW_FORM_block4: + // { + // Dwarf_Unsigned udata = 0; + + // strcpy(formName, "DW_FORM_block4"); + + // res = dwarf_formudata(attribs[i], &udata, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in DW_FORM_block4. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // dwarf_errmsg(error)); + // } + // else + // { + // unsigned int data = (unsigned int)udata; + // sprintf(value, "%d", data); + // } + + // break; + // } + + // case DW_FORM_data2: + // { + // Dwarf_Unsigned udata = 0; + + // strcpy(formName, "DW_FORM_data2"); + + // res = dwarf_formudata(attribs[i], &udata, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in DW_FORM_data2. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // dwarf_errmsg(error)); + // } + // else + // { + // unsigned short int data = (unsigned short int)udata; + // sprintf(value, "%d", data); + // } + + // break; + // } + + // case DW_FORM_data4: + // { + // Dwarf_Unsigned udata = 0; + + // strcpy(formName, "DW_FORM_data4"); + // res = dwarf_formudata(attribs[i], &udata, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // dwarf_errmsg(error)); + // } + // else + // { + // unsigned int data = (unsigned int)udata; + // sprintf(value, "%d", data); + // } + + // break; + // } + + // case DW_FORM_data8: + // { + // Dwarf_Unsigned udata = 0; + + // strcpy(formName, "DW_FORM_data8"); + + // res = dwarf_formudata(attribs[i], &udata, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // dwarf_errmsg(error)); + // } + // else + // { + // sprintf(value, "%d", udata); + // } + + // break; + // } + + // case DW_FORM_string: + // { + // char *str = 0; + + // strcpy(formName, "DW_FORM_string"); + + // res = dwarf_formstring(attribs[i], &str, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_formstring. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); + // } + // else + // { + // sprintf(value, "%s", str); + // } + + // break; + // } + + // case DW_FORM_block: + // strcpy(formName, "DW_FORM_block"); + // break; + + // case DW_FORM_block1: + // { + // Dwarf_Block *bdata = 0; + // strcpy(formName, "DW_FORM_block1"); + + // res = dwarf_formblock(attribs[i], &bdata, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_formblock. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // dwarf_errmsg(error)); + // } + // else + // { + // sprintf(value, "len: %d", bdata->bl_len); + // } + + // break; + // } + + // case DW_FORM_data1: + // { + // Dwarf_Unsigned udata = 0; + // strcpy(formName, "DW_FORM_data1"); + + // res = dwarf_formudata(attribs[i], &udata, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // dwarf_errmsg(error)); + // } + // else + // { + // uint8_t data = (uint8_t)udata; + // sprintf(value, "%u", data); + // } + + // break; + // } + + // case DW_FORM_flag: + // { + // Dwarf_Bool dwarfBool = false; + // strcpy(formName, "DW_FORM_flag"); + // char *strp = 0; + + // res = dwarf_formflag(attribs[i], &dwarfBool, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in DW_FORM_flag. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); + // } + // else + // { + // if (dwarfBool) + // { + // sprintf(value, "TRUE"); + // } + // else + // { + // sprintf(value, "FALSE"); + // } + // } + + // break; + // } + + // case DW_FORM_sdata: + // { + // Dwarf_Signed sdata = 0; + + // strcpy(formName, "DW_FORM_sdata"); + + // res = dwarf_formsdata(attribs[i], &sdata, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // dwarf_errmsg(error)); + // } + // else + // { + // sprintf(value, "%lli", sdata); + // } + + // break; + // } + + // case DW_FORM_strp: + // { + // char *strp = 0; + + // strcpy(formName, "DW_FORM_strp"); + + // res = dwarf_formstring(attribs[i], &strp, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_formstring. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); + // } + // else + // { + // char *text = dwarfStringToChar(strp); + // sprintf(value, "%s", text); + // } + + // break; + // } + + // case DW_FORM_udata: + // { + // Dwarf_Unsigned udata = 0; + + // strcpy(formName, "DW_FORM_udata"); + + // res = dwarf_formudata(attribs[i], &udata, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // dwarf_errmsg(error)); + // } + // else + // { + // sprintf(value, "%llu", udata); + // } + + // break; + // } + + // case DW_FORM_ref_addr: + // strcpy(formName, "DW_FORM_ref_addr"); + // break; + + // case DW_FORM_ref1: + // { + // Dwarf_Off ref = 0; + + // strcpy(formName, "DW_FORM_ref1"); + // res = dwarf_formref(attribs[i], &ref, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // dwarf_errmsg(error)); + // } + // else + // { + // uint8_t data = (uint8_t)ref; + // sprintf(value, "%u", data); + // } + + // break; + // } + + // case DW_FORM_ref2: + // { + // Dwarf_Off ref = 0; + + // strcpy(formName, "DW_FORM_ref1"); + // res = dwarf_formref(attribs[i], &ref, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // dwarf_errmsg(error)); + // } + // else + // { + // unsigned short int data = (unsigned short int)ref; + // sprintf(value, "%u", data); + // } + + // break; + // } + + // case DW_FORM_ref4: + // { + // Dwarf_Off ref = 0; + + // strcpy(formName, "DW_FORM_ref1"); + // res = dwarf_formref(attribs[i], &ref, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // dwarf_errmsg(error)); + // } + // else + // { + // unsigned int data = (unsigned int)ref; + // sprintf(value, "%u", data); + // } + + // break; + // } + + // case DW_FORM_ref8: + // { + // Dwarf_Off ref = 0; + + // strcpy(formName, "DW_FORM_ref1"); + // res = dwarf_formref(attribs[i], &ref, &error); + // if (res != DW_DLV_OK) + // { + // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // dwarf_errmsg(error)); + // } + // else + // { + // sprintf(value, "%llu", ref); + // } + + // break; + // } + + // case DW_FORM_ref_udata: + // strcpy(formName, "DW_FORM_ref_udata"); + // break; + + // case DW_FORM_indirect: + // strcpy(formName, "DW_FORM_indirect"); + // break; + + // case DW_FORM_sec_offset: + // strcpy(formName, "DW_FORM_sec_offset"); + // break; + + // case DW_FORM_exprloc: + // strcpy(formName, "DW_FORM_exprloc"); + // break; + + // case DW_FORM_flag_present: + // strcpy(formName, "DW_FORM_flag_present"); + // break; + + // case DW_FORM_strx: + // strcpy(formName, "DW_FORM_strx"); + // break; + + // case DW_FORM_addrx: + // strcpy(formName, "DW_FORM_addrx"); + // break; + + // case DW_FORM_ref_sup4: + // strcpy(formName, "DW_FORM_ref_sup4"); + // break; + + // case DW_FORM_strp_sup: + // strcpy(formName, "DW_FORM_strp_sup"); + // break; + + // case DW_FORM_data16: + // strcpy(formName, "DW_FORM_data16"); + // break; + + // case DW_FORM_line_strp: + // strcpy(formName, "DW_FORM_line_strp"); + // break; + + // case DW_FORM_ref_sig8: + // strcpy(formName, "DW_FORM_ref_sig8"); + // break; + + // case DW_FORM_implicit_const: + // strcpy(formName, "DW_FORM_implicit_const"); + // break; + + // case DW_FORM_loclistx: + // strcpy(formName, "DW_FORM_loclistx"); + // break; + + // case DW_FORM_rnglistx: + // strcpy(formName, "DW_FORM_rnglistx"); + // break; + + // case DW_FORM_ref_sup8: + // strcpy(formName, "DW_FORM_ref_sup8"); + // break; + + // case DW_FORM_strx1: + // strcpy(formName, "DW_FORM_strx1"); + // break; + + // case DW_FORM_strx2: + // strcpy(formName, "DW_FORM_strx2"); + // break; + + // case DW_FORM_strx3: + // strcpy(formName, "DW_FORM_strx3"); + // break; + + // case DW_FORM_strx4: + // strcpy(formName, "DW_FORM_strx4"); + // break; + + // case DW_FORM_addrx1: + // strcpy(formName, "DW_FORM_addrx1"); + // break; + + // case DW_FORM_addrx2: + // strcpy(formName, "DW_FORM_addrx2"); + // break; + + // case DW_FORM_addrx3: + // strcpy(formName, "DW_FORM_addrx3"); + // break; + + // case DW_FORM_addrx4: + // strcpy(formName, "DW_FORM_addrx4"); + // break; + + // case DW_FORM_GNU_addr_index: + // strcpy(formName, "DW_FORM_GNU_addr_index"); + // break; + + // case DW_FORM_GNU_str_index: + // strcpy(formName, "DW_FORM_GNU_str_index"); + // break; + + // case DW_FORM_GNU_ref_alt: + // strcpy(formName, "DW_FORM_GNU_ref_alt"); + // break; + + // case DW_FORM_GNU_strp_alt: + // strcpy(formName, "DW_FORM_GNU_strp_alt"); + // break; + + // default: + // sprintf(formName, "UNKNOWN (%x)", formID); + // break; + // } + // } + // } + // } + + // sprintf(line, " %-20s : %-20s (%s)\n", attribName, value, formName); + // strcat(output, line); + // } + // } + // } + + // // res = dwarf_attr(inDie, DW_AT_name, &attr_struct, &error); + // // if(res == DW_DLV_OK) + // // { + // // res = dwarf_formstring(attr_struct, &dieName, &error); + // // if(res != DW_DLV_OK) + // // { + // // logger.logError("Error in dwarf_formstring. errno=%u %s", dwarf_errno(error), + // // dwarf_errmsg(error)); + // // } + // // else + // // { + // // sprintf(line, " DW_AT_name : %s", dieName); + // // strcpy(output, line); + // // } + // // } + // // + // // res = dwarf_die_abbrev_children_flag(inDie, &hasChildrenFlag); + // // if(res != DW_DLV_OK) + // // { + // // logger.logError("Error in dwarf_die_abbrev_children_flag. errno=%u %s", dwarf_errno(error), + // // dwarf_errmsg(error)); + // // } + + // // else + // // { + // // logger.logDebug(" Has children: %s", hasChildrenFlag ? "True" : "False"); + // // } + // // + // // int dwarf_die_abbrev_children_flag(Dwarf_Die /*die*/, + // // Dwarf_Half * /*ab_has_child*/); + // // + // // res = dwarf_attrlist(inDie, &attribs, &attribCount, &error); + // // if(res != DW_DLV_OK) + // // { + // // logger.logError("Error in dwarf_attrlist. errno=%u %s", dwarf_errno(error), + // // dwarf_errmsg(error)); + // // } + // // else + // // { + // // if(attribCount > 0) + // // { + // // logger.logDebug(" Attributes:"); + // // for(uint32_t i = 0; i < attribCount; ++i) + // // { + // // Dwarf_Half attrNum; + // // res = dwarf_whatattr(attribs[i], &attrNum, &error); + // // if(res != DW_DLV_OK) + // // { + // // logger.logError("Error in dwarf_whatattr. errno=%u %s", dwarf_errno(error), + // // dwarf_errmsg(error)); + // // } + // // else + // // { + // // Dwarf_Half formID; + // // + // // switch(attrNum) + // // { + // // case DW_AT_sibling: + // // logger.logDebug(" DW_AT_sibling"); + // // break; + // // + // // case DW_AT_location: + // // logger.logDebug(" DW_AT_location"); + // // break; + // // + // // case DW_AT_name: + // // logger.logDebug(" DW_AT_name"); + // // break; + // // + // // case DW_AT_ordering: + // // logger.logDebug(" DW_AT_ordering"); + // // break; + // // + // // case DW_AT_subscr_data: + // // logger.logDebug(" DW_AT_subscr_data"); + // // break; + // // + // // case DW_AT_byte_size: + // // logger.logDebug(" DW_AT_byte_size"); + // // break; + // // + // // case DW_AT_decl_file: + // // logger.logDebug(" DW_AT_decl_file"); + // // break; + // // + // // case DW_AT_decl_line: + // // logger.logDebug(" DW_AT_decl_line"); + // // break; + // // + // // case DW_AT_type: + // // logger.logDebug(" DW_AT_type"); + // // break; + // // + // // default: + // // logger.logDebug(" 0x%02x", attrNum); + // // break; + // // } + // // + // // res = dwarf_whatform(attribs[i], &attrNum, &error); + // // if(res != DW_DLV_OK) + // // { + // // logger.logError("Error in dwarf_whatattr. errno=%u %s", dwarf_errno(error), + // // dwarf_errmsg(error)); + // // } + // // else + // // { + // // res = dwarf_whatform(attribs[i], &formID, &error); + // // if(res != DW_DLV_OK) + // // { + // // logger.logError("Error in dwarf_whatform. errno=%u %s", dwarf_errno(error), + // // dwarf_errmsg(error)); + // // } + // // else + // // { + // // switch(formID) + // // { + // // case DW_FORM_addr: + // // logger.logDebug(":DW_FORM_addr"); + // // break; + // // + // // case DW_FORM_block2: + // // logger.logDebug(":DW_FORM_block2"); + // // break; + // // + // // case DW_FORM_block4: + // // logger.logDebug(":DW_FORM_block4"); + // // break; + // // + // // case DW_FORM_data1: + // // { + // // Dwarf_Unsigned udata = 0; + // // res = dwarf_formudata(attribs[i], &udata, &error); + // // if(res != DW_DLV_OK) + // // { + // // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // // dwarf_errmsg(error)); + // // } + // // else + // // { + // // char data = (char) udata; + // // logger.logDebug(":DW_FORM_data1:%u", data); + // // } + // // break; + // // } + // // + // // case DW_FORM_data2: + // // { + // // Dwarf_Unsigned udata = 0; + // // res = dwarf_formudata(attribs[i], &udata, &error); + // // if(res != DW_DLV_OK) + // // { + // // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // // dwarf_errmsg(error)); + // // } + // // else + // // { + // // unsigned short data = (unsigned short) udata; + // // logger.logDebug(":DW_FORM_data2:%u", data); + // // } + // // break; + // // } + // // + // // case DW_FORM_data4: + // // { + // // Dwarf_Unsigned udata = 0; + // // res = dwarf_formudata(attribs[i], &udata, &error); + // // if(res != DW_DLV_OK) + // // { + // // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // // dwarf_errmsg(error)); + // // } + // // else + // // { + // // unsigned int data = (unsigned int) udata; + // // logger.logDebug(":DW_FORM_data4:%u", data); + // // } + // // break; + // // } + // // + // // case DW_FORM_data8: + // // { + // // Dwarf_Unsigned udata = 0; + // // res = dwarf_formudata(attribs[i], &udata, &error); + // // if(res != DW_DLV_OK) + // // { + // // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // // dwarf_errmsg(error)); + // // } + // // else + // // { + // // logger.logDebug(":DW_FORM_data8:%llu", udata); + // // } + // // break; + // // } + // // + // // case DW_FORM_string: + // // { + // // char *str = 0; + // // res = dwarf_formstring(attribs[i], &str, &error); + // // if(res != DW_DLV_OK) + // // { + // // logger.logError("Error in dwarf_formstring. errno=%u %s", dwarf_errno(error), + // // dwarf_errmsg(error)); + // // } + // // else + // // { + // // logger.logDebug(":DW_FORM_string:%s", str); + // // } + // // break; + // // } + // // + // // case DW_FORM_block: + // // logger.logDebug(":DW_FORM_block"); + // // break; + // // + // // case DW_FORM_sdata: + // // logger.logDebug(":DW_FORM_sdata"); + // // break; + // // + // // case DW_FORM_strp: + // // { + // // char *strp = 0; + // // res = dwarf_formstring(attribs[i], &strp, &error); + // // if(res != DW_DLV_OK) + // // { + // // logger.logError("Error in dwarf_formstring. errno=%u %s", dwarf_errno(error), + // // dwarf_errmsg(error)); + // // } + // // else + // // { + // // char *text = dwarfStringToChar(strp); + // // logger.logDebug(":DW_FORM_strp:%s", text); + // // } + // // break; + // // } + // // + // // case DW_FORM_udata: + // // { + // // Dwarf_Unsigned udata = 0; + // // res = dwarf_formudata(attribs[i], &udata, &error); + // // if(res != DW_DLV_OK) + // // { + // // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // // dwarf_errmsg(error)); + // // } + // // else + // // { + // // logger.logDebug(":DW_FORM_udata:%llu", udata); + // // } + // // break; + // // } + // // + // // case DW_FORM_ref_addr: + // // logger.logDebug(":DW_FORM_ref_addr"); + // // break; + // // + // // case DW_FORM_ref1: + // // { + // // Dwarf_Off ref = 0; + // // res = dwarf_formref(attribs[i], &ref, &error); + // // if(res != DW_DLV_OK) + // // { + // // logger.logError("Error in dwarf_formudata. line=%u errno=%u %s", __LINE__, dwarf_errno(error), + // // dwarf_errmsg(error)); + // // } + // // else + // // { + // // char data = (char) ref; + // // logger.logDebug(":DW_FORM_ref1:%u", data); + // // } + // // break; + // // } + // // + // // case DW_FORM_ref2: + // // { + // // Dwarf_Off ref = 0; + // // res = dwarf_formref(attribs[i], &ref, &error); + // // if(res != DW_DLV_OK) + // // { + // // logger.logError("Error in dwarf_formref. errno=%u %s", dwarf_errno(error), + // // dwarf_errmsg(error)); + // // } + // // else + // // { + // // unsigned short int data = (unsigned short int) ref; + // // logger.logDebug(":DW_FORM_ref2:%u", data); + // // } + // // break; + // // } + // // + // // case DW_FORM_ref4: + // // { + // // Dwarf_Off ref = 0; + // // res = dwarf_formref(attribs[i], &ref, &error); + // // if(res != DW_DLV_OK) + // // { + // // logger.logError("Error in dwarf_formref. errno=%u %s", dwarf_errno(error), + // // dwarf_errmsg(error)); + // // } + // // else + // // { + // // unsigned int data = (unsigned int) ref; + // // logger.logDebug(":DW_FORM_ref4:%u", data); + // // } + // // break; + // // } + // // + // // case DW_FORM_ref8: + // // { + // // Dwarf_Off ref = 0; + // // res = dwarf_formref(attribs[i], &ref, &error); + // // if(res != DW_DLV_OK) + // // { + // // logger.logError("Error in dwarf_formref. errno=%u %s", dwarf_errno(error), + // // dwarf_errmsg(error)); + // // } + // // else + // // { + // // logger.logDebug(":DW_FORM_ref4:%llu", ref); + // // } + // // break; + // // } + // // + // // case DW_FORM_ref_udata: + // // logger.logDebug(":DW_FORM_ref_udata"); + // // break; + // // + // // case DW_FORM_indirect: + // // logger.logDebug(":DW_FORM_indirect"); + // // break; + // // + // // case DW_FORM_sec_offset: + // // logger.logDebug(":DW_FORM_sec_offset"); + // // break; + // // + // // case DW_FORM_exprloc: + // // logger.logDebug(":DW_FORM_exprloc"); + // // break; + // // + // // case DW_FORM_flag_present: + // // logger.logDebug(":DW_FORM_flag_present"); + // // break; + // // + // // case DW_FORM_ref_sig8: + // // logger.logDebug(":DW_FORM_ref_sig8"); + // // break; + // // + // // default: + // // logger.logDebug(":0x%02x", formID); + // // break; + // // + // // } + // // } + // // } + // // } + // // } + // // logger.logDebug("\n"); + // // } + // // } + + // logger.logDebug(output); + // } } Symbol *Juicer::process_DW_TAG_base_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die inDie) @@ -3226,10 +3113,11 @@ Symbol *Juicer::process_DW_TAG_base_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Di Dwarf_Attribute attr_struct; Symbol *outSymbol = nullptr; std::string cName; - Dwarf_Error error = 0; + Dwarf_Error error = 0; + Dwarf_Signed encodingValue = -1; /* Get the name attribute of this Die. */ - res = dwarf_attr(inDie, DW_AT_name, &attr_struct, &error); + res = dwarf_attr(inDie, DW_AT_name, &attr_struct, &error); if (res != DW_DLV_OK) { logger.logError("Error in dwarf_attr(DW_AT_name). %u errno=%u %s", __LINE__, dwarf_errno(error), dwarf_errmsg(error)); @@ -3256,6 +3144,21 @@ Symbol *Juicer::process_DW_TAG_base_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Di cName = dieName; } + res = dwarf_attr(inDie, DW_AT_encoding, &attr_struct, &error); + if (res != DW_DLV_OK) + { + logger.logError("Error in dwarf_attr(DW_AT_name). %u errno=%u %s", __LINE__, dwarf_errno(error), dwarf_errmsg(error)); + } + + if (res == DW_DLV_OK) + { + res = dwarf_formsdata(attr_struct, &encodingValue, &error); + if (res != DW_DLV_OK) + { + logger.logError("Error in dwarf_formstring. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); + } + } + outSymbol = elf.getSymbol(cName); if (outSymbol == 0) @@ -3316,7 +3219,16 @@ Symbol *Juicer::process_DW_TAG_base_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Di if (pathIndex != 0) { - Artifact newArtifact{elf, dbgSourceFiles.at(pathIndex - 1)}; + /** + * Why we are checking against 0 as per DWARF section 2.14: + * + * The value of the DW_AT_decl_file attribute corresponds to a file number from the line number + * information table for the compilation unit containing the debugging information entry and + * represents the source file in which the declaration appeared (see Section 6.2 ). The value 0 + * indicates that no source file has been specified. + * + */ + Artifact newArtifact{elf, getdbgSourceFile(elf, pathIndex)}; std::string checkSum = generateMD5SumForFile(newArtifact.getFilePath()); newArtifact.setMD5(checkSum); outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact); @@ -3342,6 +3254,7 @@ Symbol *Juicer::process_DW_TAG_base_type(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Di } } } + outSymbol->setEncoding(encodingValue); } } @@ -3355,6 +3268,7 @@ void Juicer::process_DW_TAG_enumeration_type(ElfFile &elf, Symbol &symbol, Dwarf Dwarf_Die enumeratorDie = 0; Dwarf_Signed encodingValue; Dwarf_Error error = 0; + std::string symbolEncoding{}; /* Get the fields by getting the first child. */ if (res == DW_DLV_OK) @@ -3446,13 +3360,15 @@ void Juicer::process_DW_TAG_enumeration_type(ElfFile &elf, Symbol &symbol, Dwarf { case DW_ATE_signed: { - res = dwarf_formsdata(attr_struct, &enumeratorValue, &error); + res = dwarf_formsdata(attr_struct, &enumeratorValue, &error); + symbolEncoding = "DW_ATE_signed"; break; } case DW_ATE_unsigned: { - res = dwarf_formudata(attr_struct, (Dwarf_Unsigned *)&enumeratorValue, &error); + res = dwarf_formudata(attr_struct, (Dwarf_Unsigned *)&enumeratorValue, &error); + symbolEncoding = "DW_ATE_unsigned"; break; } default: @@ -3474,6 +3390,7 @@ void Juicer::process_DW_TAG_enumeration_type(ElfFile &elf, Symbol &symbol, Dwarf Dwarf_Die siblingDie = 0; symbol.addEnumeration(sEnumeratorName, enumeratorValue); + symbol.setEncoding(encodingValue); res = dwarf_siblingof(dbg, enumeratorDie, &siblingDie, &error); if (res == DW_DLV_ERROR) @@ -3545,6 +3462,10 @@ Symbol *Juicer::process_DW_TAG_typedef(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die /* Set the error code so we don't do anymore processing. */ res = DW_DLV_ERROR; } + else + { + // FIXME:Handle else case + } } /* Get the size of this datatype. */ @@ -3588,17 +3509,26 @@ Symbol *Juicer::process_DW_TAG_typedef(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die if (pathIndex != 0) { - Artifact newArtifact{elf, dbgSourceFiles.at(pathIndex - 1)}; + /** + * Why we are checking against 0 as per DWARF section 2.14: + * + * The value of the DW_AT_decl_file attribute corresponds to a file number from the line number + * information table for the compilation unit containing the debugging information entry and + * represents the source file in which the declaration appeared (see Section 6.2 ). The value 0 + * indicates that no source file has been specified. + * + */ + Artifact newArtifact{elf, getdbgSourceFile(elf, pathIndex)}; std::string checkSum = generateMD5SumForFile(newArtifact.getFilePath()); newArtifact.setMD5(checkSum); - outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact); + outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact, baseTypeSymbol); } 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, baseTypeSymbol); } } } @@ -4038,14 +3968,7 @@ void Juicer::addBitFields(Dwarf_Die dataMemberDie, Field &dataMemberField) Dwarf_Unsigned bit_size = 0; Dwarf_Error error = 0; - res = dwarf_attr(dataMemberDie, DW_AT_data_bit_offset, &attr_struct, &error); - - if (DW_DLV_OK == res) - { - res = dwarf_formudata(attr_struct, &bit_offset, &error); - } - - res = dwarf_attr(dataMemberDie, DW_AT_bit_size, &attr_struct, &error); + res = dwarf_attr(dataMemberDie, DW_AT_bit_size, &attr_struct, &error); if (DW_DLV_OK == res) { @@ -4077,13 +4000,13 @@ void Juicer::addBitFields(Dwarf_Die dataMemberDie, Field &dataMemberField) */ bool Juicer::isDWARFVersionSupported(Dwarf_Die inDie) { - bool isSupported = true; + bool isSupported = true; - Dwarf_Half dwarfVersion = 0; + dwarfVersion = 0; - Dwarf_Half dwarfOffset = 0; + Dwarf_Half dwarfOffset = 0; - int rec = dwarf_get_version_of_die(inDie, &dwarfVersion, &dwarfOffset); + int rec = dwarf_get_version_of_die(inDie, &dwarfVersion, &dwarfOffset); if (rec != DW_DLV_OK) { @@ -4217,7 +4140,16 @@ int Juicer::getDieAndSiblings(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die in_die, i if (pathIndex != 0) { - Artifact newArtifact{elf, dbgSourceFiles.at(pathIndex - 1)}; + /** + * Why we are checking against 0 as per DWARF section 2.14: + * + * The value of the DW_AT_decl_file attribute corresponds to a file number from the line number + * information table for the compilation unit containing the debugging information entry and + * represents the source file in which the declaration appeared (see Section 6.2 ). The value 0 + * indicates that no source file has been specified. + * + */ + Artifact newArtifact{elf, getdbgSourceFile(elf, pathIndex)}; std::string checkSum = generateMD5SumForFile(newArtifact.getFilePath()); newArtifact.setMD5(checkSum); outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact); @@ -4230,6 +4162,13 @@ int Juicer::getDieAndSiblings(ElfFile &elf, Dwarf_Debug dbg, Dwarf_Die in_die, i outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact); } } + else + { + Artifact newArtifact{elf, "NOT_FOUND:" + sDieName}; + std::string checkSum{}; + newArtifact.setMD5(checkSum); + outSymbol = elf.addSymbol(sDieName, byteSize, newArtifact); + } process_DW_TAG_structure_type(elf, *outSymbol, dbg, cur_die); } @@ -4338,11 +4277,6 @@ int Juicer::printDieData(Dwarf_Debug dbg, Dwarf_Die print_me, uint32_t level) /* Do nothing */ } - if (strcmp(name, "CFE_SB_TlmHdr_t") == 0) - { - printf("hello\n"); - } - if (tag != DW_TAG_structure_type) { res = dwarf_tag(print_me, &tag, &error); @@ -4422,42 +4356,337 @@ std::map> Juicer::getObjDataFromElf(ElfFile *e if (buffer[EI_CLASS] == ELFCLASS64) { - size_t elfSectionCount = -1; - int res = elf_getshdrnum(elf, &elfSectionCount); - - for (size_t i = 0; i < elfSectionCount; i++) + elfFileObj->setElfClass(ELFCLASS64); { - Elf_Scn *section = elf_getscn(elf, i); - std::cout << "section" << section << std::endl; - } - std::cout << "res:" << res << std::endl; + if (elf != NULL) + { + elf_hdr_64 = elf64_getehdr(elf); + size_t elfSectionCount = 0; + int res = elf_getshdrnum(elf, &elfSectionCount); - if (elf != NULL) - { - elf_hdr_64 = elf64_getehdr(elf); + logger.logInfo("Found %d elf sections", elfSectionCount); - ident_buffer = elf_hdr_64->e_ident; - if (ident_buffer[EI_DATA] == ELFDATA2LSB) - { - rc = JUICER_ENDIAN_LITTLE; - } - else if (ident_buffer[EI_DATA] == ELFDATA2MSB) - { - rc = JUICER_ENDIAN_BIG; + for (size_t i = 0; i < elfSectionCount; i++) + { + Elf_Scn *section = elf_getscn(elf, i); + + Elf64_Shdr *sectionHeader = elf64_getshdr(section); + + elfFileObj->addElf64SectionHeader(*sectionHeader); + + Elf32_Word sectionSize = sectionHeader->sh_size; + Elf32_Word sectionTableEntrySize = sectionHeader->sh_entsize; /*Only relevant for tables such as SHT_SYMTAB*/ + + switch (sectionHeader->sh_type) + { + case SHT_NULL: + { + logger.logWarning("Section SHT_NULL(%d) not supported.", SHT_NULL); + break; + } + case SHT_PROGBITS: + { + logger.logWarning("Section SHT_PROGBITS(%d) not supported.", SHT_PROGBITS); + break; + } + case SHT_SYMTAB: + { + logger.logInfo("Extracting SHT_SYMTAB(%d) at index(%d).", SHT_SYMTAB, i); + logger.logInfo("Section Size:%d", sectionSize); + logger.logInfo("Section Table Entry Size:%d", sectionTableEntrySize); + + Elf64_Word sectionSize = sectionHeader->sh_size; + Elf64_Word sectionTableEntrySize = sectionHeader->sh_entsize; /*Only relevant for tables such as SHT_SYMTAB*/ + + int numberOfSymbols = sectionSize / sectionTableEntrySize; + + logger.logInfo("Found %d symbols in Elf", numberOfSymbols); + + Elf_Data *elfData = nullptr; + elfData = elf_getdata(section, elfData); + if (elfData != nullptr) + { + logger.logInfo("elfData Size:%d", elfData->d_size); + + Elf64_Sym *sectionTableData = (Elf64_Sym *)elfData->d_buf; + + size_t strTableIndex = sectionHeader->sh_link; + logger.logInfo("String table index for symbols:%d", strTableIndex); + for (int i = 0; i < numberOfSymbols; i++) + { + Elf64_Sym *symbol = sectionTableData; + + uint32_t symbolSectionFileOffset = 0; + uint32_t symbolSectionStrTableFileOffset = 0; + + if (symbol->st_size > 0) + { + if (symbol->st_shndx == SHN_COMMON) + { + logger.logWarning("Ignoring symbol since it has SHN_COMMON as its st_shndx"); + } + else + { + Elf_Scn *stringTableSection = elf_getscn(elf, strTableIndex); + Elf64_Shdr *stringTableSectionHeader = elf64_getshdr(stringTableSection); + + Elf64_Xword stringTableSectionHeaderSectionSize = stringTableSectionHeader->sh_size; + + if (symbol->st_name > 0) + { + char *currentStrTblPtr = elf_strptr(elf, strTableIndex, symbol->st_name); + + if (currentStrTblPtr != nullptr) + { + int stringTableCursor = 0; + std::string name{}; + while (currentStrTblPtr[stringTableCursor] != '\0') + { + name.push_back(currentStrTblPtr[stringTableCursor]); + stringTableCursor++; + } + + logger.logInfo( + "Found symbol %s with size: %d, st_value:%u, st_name:%u, st_info:%u, st_other:%u, st_shndx:%u\n", + name.c_str(), symbol->st_size, symbol->st_value, symbol->st_name, symbol->st_info, symbol->st_other, + symbol->st_shndx); + + symbolSectionStrTableFileOffset = stringTableSectionHeader->sh_offset; + + // TODO:Map it to DWARF here. + Elf_Scn *symbolSectionData = elf_getscn(elf, symbol->st_shndx); + + Elf64_Shdr *symbolSectionHeader = elf64_getshdr(symbolSectionData); + + if (symbolSectionHeader != nullptr) + { + // std::cout << "symbol data section file offset-->" + // << symbolSectionHeader->sh_offset << std::endl; + symbolSectionFileOffset = symbolSectionHeader->sh_offset; + } + + Elf_Data *symbolSectionDataContents = nullptr; + + symbolSectionDataContents = elf_getdata(symbolSectionData, symbolSectionDataContents); + + if (symbolSectionDataContents->d_type == ELF_T_BYTE) + { + uint8_t *symbolDataCursor = (uint8_t *)symbolSectionDataContents->d_buf; + + std::vector symbolData = std::vector(); + + if (symbolDataCursor != nullptr) + { + for (int i = symbol->st_value; i < symbol->st_size; i++) + { + symbolData.push_back(symbolDataCursor[i]); + } + } + else + { + logger.logWarning("Did not find size for symbol \"%d\"", name); + } + + symbolToData.insert({name, symbolData}); + } + else + { + logger.logWarning("Symbol %s ignored since ELF_T_BYTE was NOT found. Found %d type instead.", + name.c_str(), symbolSectionDataContents->d_type); + } + } + } + } + } + + elfFileObj->addElf64SymbolTableSymbol(Elf64Symbol{*symbol, symbolSectionFileOffset, symbolSectionStrTableFileOffset}); + sectionTableData++; + } + } + + break; + } + case SHT_STRTAB: + { + logger.logWarning("Extracting SHT_STRTAB(%d) from section #%d.", SHT_STRTAB, i); + break; + } + case SHT_RELA: + { + logger.logWarning("Section SHT_RELA(%d) not supported.", SHT_RELA); + break; + } + case SHT_HASH: + { + logger.logWarning("Section SHT_HASH(%d) not supported.", SHT_HASH); + break; + } + case SHT_DYNAMIC: + { + logger.logWarning("Section %d not supported.", SHT_DYNAMIC); + break; + } + case SHT_NOTE: + { + logger.logWarning("Section SHT_NOTE(%d) not supported.", SHT_NOTE); + break; + } + case SHT_NOBITS: + { + logger.logWarning("Section SHT_NOBITS(%d) not supported.", SHT_NOBITS); + break; + } + case SHT_REL: + { + logger.logWarning("Section SHT_REL(%d) not supported.", SHT_REL); + break; + } + case SHT_SHLIB: + { + logger.logWarning("Section SHT_SHLIB(%d) not supported.", SHT_SHLIB); + break; + } + case SHT_DYNSYM: + { + logger.logWarning("Section SHT_DYNSYM(%d) not supported.", SHT_DYNSYM); + break; + } + case SHT_INIT_ARRAY: + { + logger.logWarning("Section SHT_INIT_ARRAY(%d) not supported.", SHT_INIT_ARRAY); + break; + } + case SHT_FINI_ARRAY: + { + logger.logWarning("Section SHT_FINI_ARRAY(%d) not supported.", SHT_FINI_ARRAY); + break; + } + case SHT_PREINIT_ARRAY: + { + logger.logWarning("Section SHT_PREINIT_ARRAY(%d) not supported.", SHT_PREINIT_ARRAY); + break; + } + case SHT_GROUP: + { + logger.logWarning("Section SHT_GROUP(%d) not supported.", SHT_GROUP); + break; + } + case SHT_SYMTAB_SHNDX: + { + logger.logWarning("Section SHT_SYMTAB_SHNDX(%d) not supported.", SHT_SYMTAB_SHNDX); + break; + } + case SHT_NUM: + { + logger.logWarning("Section SHT_NUM(%d) not supported.", SHT_NUM); + break; + } + case SHT_LOOS: + { + logger.logWarning("Section SHT_LOOS(%d) not supported.", SHT_LOOS); + break; + } + case SHT_GNU_ATTRIBUTES: + { + logger.logWarning("Section SHT_GNU_ATTRIBUTES(%d) not supported.", SHT_GNU_ATTRIBUTES); + break; + } + case SHT_GNU_HASH: + { + logger.logWarning("Section SHT_GNU_HASH(%d) not supported.", SHT_GNU_HASH); + break; + } + case SHT_GNU_LIBLIST: + { + logger.logWarning("Section %d not supported.", SHT_GNU_LIBLIST); + break; + } + case SHT_CHECKSUM: + { + logger.logWarning("Section %d not supported.", SHT_CHECKSUM); + break; + } + // case SHT_LOSUNW: SHT_LOSUNW and SHT_SUNW_move are the same value, for some reason. + case SHT_SUNW_move: + { + logger.logWarning("Section %d not supported.", SHT_SUNW_move); + break; + } + case SHT_SUNW_COMDAT: + { + logger.logWarning("Section %d not supported.", SHT_SUNW_COMDAT); + break; + } + case SHT_SUNW_syminfo: + { + logger.logWarning("Section %d not supported.", SHT_SUNW_syminfo); + break; + } + case SHT_GNU_verdef: + { + logger.logWarning("Section %d not supported.", SHT_GNU_verdef); + break; + } + case SHT_GNU_verneed: + { + logger.logWarning("Section %d not supported.", SHT_GNU_verneed); + break; + } + + // case SHT_HISUNW: SHT_GNU_versym and SHT_HISUNW are the same value, for some reason. + case SHT_HIOS: + { + logger.logWarning("Section %d not supported.", SHT_HIOS); + break; + } + case SHT_LOPROC: + { + logger.logWarning("Section %d not supported.", SHT_LOPROC); + break; + } + case SHT_HIPROC: + { + logger.logWarning("Section %d not supported.", SHT_HIPROC); + break; + } + case SHT_LOUSER: + { + logger.logWarning("Section %d not supported.", SHT_LOUSER); + break; + } + case SHT_HIUSER: + { + logger.logWarning("Section %d not supported.", SHT_HIUSER); + break; + } + } + } + + ident_buffer = elf_hdr_64->e_ident; + + if (ident_buffer[EI_DATA] == ELFDATA2LSB) + { + rc = JUICER_ENDIAN_LITTLE; + } + else if (ident_buffer[EI_DATA] == ELFDATA2MSB) + { + rc = JUICER_ENDIAN_BIG; + } + else + { + rc = JUICER_ENDIAN_UNKNOWN; + } + elf_end(elf); } else { - rc = JUICER_ENDIAN_UNKNOWN; + logger.logError("elf_begin failed. errno=%d %s", errno, strerror(errno)); } - elf_end(elf); - } - else - { - logger.logError("elf_begin failed. errno=%d %s", errno, strerror(errno)); } } else if (buffer[EI_CLASS] == ELFCLASS32) { + elfFileObj->setElfClass(ELFCLASS32); if (elf != NULL) { elf_hdr_32 = elf32_getehdr(elf); @@ -4550,8 +4779,6 @@ std::map> Juicer::getObjDataFromElf(ElfFile *e name.c_str(), symbol->st_size, symbol->st_value, symbol->st_name, symbol->st_info, symbol->st_other, symbol->st_shndx); - std::cout << "stringTableSectionHeader file offset:" << stringTableSectionHeader->sh_offset << std::endl; - symbolSectionStrTableFileOffset = stringTableSectionHeader->sh_offset; // TODO:Map it to DWARF here. @@ -4561,8 +4788,6 @@ std::map> Juicer::getObjDataFromElf(ElfFile *e if (symbolSectionHeader != nullptr) { - // std::cout << "symbol data section file offset-->" << - // symbolSectionHeader->sh_offset << std::endl; symbolSectionFileOffset = symbolSectionHeader->sh_offset; } @@ -4575,8 +4800,6 @@ std::map> Juicer::getObjDataFromElf(ElfFile *e uint8_t *symbolDataCursor = (uint8_t *)symbolSectionDataContents->d_buf; std::vector symbolData = std::vector(); - std::cout << "ELF32_ST_TYPE:" << ELF32_ST_TYPE(symbol->st_info) << std::endl; - std::cout << "ELF32_ST_BIND:" << ELF32_ST_BIND(symbol->st_info) << std::endl; if (symbolDataCursor != nullptr) { @@ -4763,11 +4986,7 @@ std::map> Juicer::getObjDataFromElf(ElfFile *e break; } } - - // std::cout << "sh_type" << sectionHeader->sh_type << std::endl; } - std::cout << "res:" << res << std::endl; - ident_buffer = elf_hdr_32->e_ident; if (ident_buffer[EI_DATA] == ELFDATA2LSB) @@ -4930,7 +5149,8 @@ int Juicer::parse(std::string &elfFilePath) if (JUICER_OK == return_value) { /* Initialize the Dwarf library. This will open the file. */ - dwarf_value = dwarf_init(elfFile, DW_DLC_READ, errhand, errarg, &dbg, &error); + /* Initialize the Dwarf library. This will open the file. */ + dwarf_value = dwarf_init_b(elfFile, DW_DLC_READ, groupNumber, errhand, errarg, &dbg, &error); if (dwarf_value != DW_DLV_OK) { logger.logError("Failed to read the dwarf"); @@ -5062,26 +5282,6 @@ uint32_t Juicer::calcArraySizeForDimension(Dwarf_Debug dbg, Dwarf_Die dieSubrang return dimSize; } -/** - * - * @return The number of elements in the die array entry, including all dimensions. It is assumed that die is of type - * DW_TAG_array_type. - */ -int Juicer::calcArraySizeForAllDims(Dwarf_Debug dbg, Dwarf_Die die) -{ - int arraySize = 0; - std::vector children = getChildrenVector(dbg, die); - - for (auto child : children) - { - if (arraySize == 0) arraySize = 1; - - arraySize = arraySize * calcArraySizeForDimension(dbg, child); - } - - return arraySize; -} - /** * Assuming that die is a DW_TAG_array_type, iterate through each DW_TAG_subrange_type and return * a std::vector with all them as Dimension objects @@ -5174,35 +5374,6 @@ int Juicer::getNumberOfSiblingsForDie(Dwarf_Debug dbg, Dwarf_Die die) return siblingCount; } - -std::vector Juicer::getSiblingsVector(Dwarf_Debug dbg, Dwarf_Die die) -{ - int res = DW_DLV_OK; - std::vector siblingList{}; - - Dwarf_Die sibling_die; - - Dwarf_Error error = 0; - - int siblingCount = getNumberOfSiblingsForDie(dbg, die); - - for (int sibling = 0; sibling < siblingCount; sibling++) - { - res = dwarf_siblingof(dbg, die, &sibling_die, &error); - if (res != DW_DLV_OK) - { - logger.logWarning("Error in dwarf_siblingof. errno=%u %s", dwarf_errno(error), dwarf_errmsg(error)); - } - else - { - siblingList.push_back(sibling_die); - die = sibling_die; - } - } - - return siblingList; -} - /** *@brief Get all of the children of the die in a nice STL vector. */ @@ -5283,3 +5454,32 @@ std::string Juicer::generateMD5SumForFile(std::string filePath) auto md5 = hex.str(); return md5; } + +/** + * handles debug source files lookups for different DWARF versions. + * It is assumed the pathIndex is the value of DW_AT_decl_file attribute + */ +std::string &Juicer::getdbgSourceFile(ElfFile &elf, int pathIndex) +{ + switch (dwarfVersion) + { + /** + * + * As per section 1.4 (Changes from Version 4 to Version 5) of DWARF5 + * + * The line number table header is substantially revised. + **/ + + case 4: + { + return dbgSourceFiles.at(pathIndex - 1); + } + case 5: + { + return dbgSourceFiles.at(pathIndex); + } + } + return dbgSourceFiles.at(pathIndex); +} + +unsigned int Juicer::getDwarfVersion() { return dwarfVersion; } \ No newline at end of file diff --git a/src/Juicer.h b/src/Juicer.h index bef00721..0a4fece6 100644 --- a/src/Juicer.h +++ b/src/Juicer.h @@ -101,6 +101,10 @@ class Juicer void setExtras(bool extras) { this->extras = extras; } + void setGroupNumber(unsigned int groupNumber) { this->groupNumber = groupNumber; }; + + unsigned int getDwarfVersion(); + private: Dwarf_Debug dbg = 0; int res = DW_DLV_ERROR; @@ -129,24 +133,26 @@ class Juicer Symbol* getBaseTypeSymbol(ElfFile& elf, Dwarf_Die inDie, DimensionList& multiplicity); void DisplayDie(Dwarf_Die inDie, uint32_t level); - std::vector getSiblingsVector(Dwarf_Debug dbg, Dwarf_Die die); std::vector getChildrenVector(Dwarf_Debug dbg, Dwarf_Die die); int getNumberOfSiblingsForDie(Dwarf_Debug dbg, Dwarf_Die die); uint32_t calcArraySizeForDimension(Dwarf_Debug dbg, Dwarf_Die die); - int calcArraySizeForAllDims(Dwarf_Debug dbg, Dwarf_Die die); DimensionList getDimList(Dwarf_Debug dbg, Dwarf_Die die); std::vector dbgSourceFiles{}; std::string generateMD5SumForFile(std::string filePath); + std::string& getdbgSourceFile(ElfFile& elf, int pathIndex); DefineMacro getDefineMacro(Dwarf_Half macro_operator, Dwarf_Macro_Context mac_context, int i, Dwarf_Unsigned line_number, Dwarf_Unsigned index, Dwarf_Unsigned offset, const char* macro_string, Dwarf_Half& forms_count, Dwarf_Error& error, Dwarf_Die cu_die, ElfFile& elf); DefineMacro getDefineMacroFromString(std::string macro_string); std::map> getObjDataFromElf(ElfFile* elfFileObj); bool extras; + + unsigned int groupNumber{0}; + Dwarf_Half dwarfVersion = 0; }; #endif /* JUICER_H_ */ diff --git a/src/LoggerInstance.h b/src/LoggerInstance.h index 86645865..8621d372 100644 --- a/src/LoggerInstance.h +++ b/src/LoggerInstance.h @@ -64,7 +64,7 @@ class LoggerInstance void LogEvent(LoggerCriticality_t criticality, const std::string &message); private: - LoggerInstance(LoggerInstance const &){}; // copy constructor is private + LoggerInstance(LoggerInstance const &) {}; // copy constructor is private LoggerInstance &operator=(LoggerInstance const &) { return *this; }; // assignment operator is private static LoggerInstance *m_pInstance; std::ofstream logFile; diff --git a/src/SQLiteDB.cpp b/src/SQLiteDB.cpp index 242a504d..f6aaabce 100644 --- a/src/SQLiteDB.cpp +++ b/src/SQLiteDB.cpp @@ -109,6 +109,32 @@ bool SQLiteDB::doesSymbolExist(std::string name) return row_count == 0 ? false : true; } +bool SQLiteDB::doEncodingsExist() +{ + int32_t row_count = 0; + + int rc = SQLITE_OK; + + char* errorMessage = nullptr; + + std::string countRowsQuery{"SELECT COUNT(*) FROM encodings"}; + countRowsQuery += ""; + countRowsQuery += ";"; + + rc = sqlite3_exec(database, countRowsQuery.c_str(), SQLiteDB::doesRowExistCallback, &row_count, &errorMessage); + + if (SQLITE_OK != rc) + { + logger.logWarning( + "Looks like there was a problem sending query \"%s\" " + "to the database.", + countRowsQuery.c_str()); + logger.logError("%s", errorMessage); + row_count = 0; + } + return row_count == 0 ? false : true; +} + /** *@brief Checks if the symbol called name exists on the symbols table. * @@ -302,6 +328,22 @@ int SQLiteDB::write(ElfFile& inElf) rc = SQLITEDB_ERROR; } + rc = writeEncodingsToDatabase(inElf); + + if (SQLITEDB_ERROR != rc) + { + logger.logDebug( + "Variable entries were written to the variables schema " + "with SQLITE_OK status."); + } + else + { + logger.logDebug( + "There was an error while writing variable entries to the" + " database."); + rc = SQLITEDB_ERROR; + } + rc = writeSymbolsToDatabase(inElf); if (SQLITEDB_ERROR != rc) @@ -484,9 +526,7 @@ int SQLiteDB::writeElfToDatabase(ElfFile& inElf) */ int SQLiteDB::writeMacrosToDatabase(ElfFile& inElf) { - int rc = SQLITEDB_OK; - char* errorMessage = NULL; - + int rc = SQLITEDB_OK; for (auto macro : inElf.getDefineMacros()) { /* @@ -494,40 +534,61 @@ int SQLiteDB::writeMacrosToDatabase(ElfFile& inElf) * but I'm not sure what is the best way to do that without it being * messy. */ - std::string writeMacroQuery{}; - writeMacroQuery += - "INSERT INTO macros(name, value) " - "VALUES(\""; - writeMacroQuery += macro.getName(); - writeMacroQuery += "\","; - writeMacroQuery += "\""; - writeMacroQuery += macro.getValue(); - writeMacroQuery += "\""; - writeMacroQuery += ");"; + // Create a SQL statement with placeholders + sqlite3_stmt* stmt; + const char* sql = "INSERT INTO macros (name, value) VALUES (?, ?);"; - logger.logDebug("Sending \"%s\" query to database.", writeMacroQuery.c_str()); + // Prepare the SQL statement + rc = sqlite3_prepare_v2(database, sql, -1, &stmt, NULL); - rc = sqlite3_exec(database, writeMacroQuery.c_str(), NULL, NULL, &errorMessage); - - if (SQLITE_OK == rc) + if (rc != SQLITE_OK) { - logger.logDebug( - "Elf values were written to the macros schema with " - "SQLITE_OK status."); + std::cerr << "SQL error: " << sqlite3_errmsg(database) << std::endl; } else { - if (sqlite3_extended_errcode(database) == SQLITE_CONSTRAINT_UNIQUE) + // Bind values to placeholders + sqlite3_bind_text(stmt, 1, macro.getName().c_str(), -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 2, macro.getValue().c_str(), -1, SQLITE_STATIC); + + // Execute the SQL statement + if (sqlite3_step(stmt) != SQLITE_DONE) { - logger.logDebug("%s.", errorMessage); - rc = SQLITE_OK; + const char* errorMessage = sqlite3_errmsg(database); + if (SQLITE_OK == rc) + { + logger.logDebug( + "Elf values were written to the macros schema with " + "SQLITE_OK status."); + } + else + { + if (sqlite3_extended_errcode(database) == SQLITE_CONSTRAINT_UNIQUE) + { + logger.logDebug("%s.", errorMessage); + rc = SQLITE_OK; + } + else + { + logger.logDebug("There was an error while writing data to the elfs table."); + logger.logDebug("%s.", errorMessage); + rc = SQLITEDB_ERROR; + } + } + } + + // Finalize the statement + rc = sqlite3_finalize(stmt); + if (rc != SQLITE_OK) + { + logger.logDebug("There was an error while finalizing the sql statement for encodings table."); } else { - logger.logDebug("There was an error while writing data to the elfs table."); - logger.logDebug("%s.", errorMessage); - rc = SQLITEDB_ERROR; + // sqlite3_int64 lastRowId = sqlite3_last_insert_rowid(database); + + // inElf.encodingsMap.at(encoding.first).setId(lastRowId); } } } @@ -552,11 +613,7 @@ int SQLiteDB::writeVariablesToDatabase(ElfFile& inElf) for (auto variable : inElf.getVariables()) { - // std::string symbolInitializedDataName = symbolDataPair.first; - // std::vector symbolInitializedData = symbolDataPair.second; - inElf.getInitializedSymbolData(); - uint32_t typeID; /* * @todo I want to store these SQLite magical values into MACROS, @@ -572,7 +629,7 @@ int SQLiteDB::writeVariablesToDatabase(ElfFile& inElf) writeVariableQuery += variable.getName(); writeVariableQuery += "\""; writeVariableQuery += ","; - writeVariableQuery += std::to_string(inElf.getId()); + writeVariableQuery += std::to_string(variable.getElf().getId()); writeVariableQuery += ","; writeVariableQuery += std::to_string(variable.getType().getId()); @@ -585,7 +642,7 @@ int SQLiteDB::writeVariablesToDatabase(ElfFile& inElf) writeVariableQuery += ","; writeVariableQuery += "\""; - writeVariableQuery += variable.getShortDescription(); + writeVariableQuery += variable.getLongDescription(); writeVariableQuery += "\""; writeVariableQuery += ");"; @@ -634,78 +691,153 @@ int SQLiteDB::writeElfSectionsToDatabase(ElfFile& inElf) int rc = SQLITEDB_OK; char* errorMessage = NULL; - for (auto elf32Section : inElf.getElf32Headers()) + switch (inElf.getElfClass()) { - // std::string symbolInitializedDataName = symbolDataPair.first; - // std::vector symbolInitializedData = symbolDataPair.second; + case ELFCLASS32: + { + for (auto elf32Section : inElf.getElf32Headers()) + { + inElf.getInitializedSymbolData(); - inElf.getInitializedSymbolData(); - uint32_t typeID; + /* + * @todo I want to store these SQLite magical values into MACROS, + * but I'm not sure what is the best way to do that without it being + * messy. + */ + std::string writeElfSectionsQuery{}; - /* - * @todo I want to store these SQLite magical values into MACROS, - * but I'm not sure what is the best way to do that without it being - * messy. - */ - std::string writeElfSectionsQuery{}; + /** + *@todo Not sure if I should make a seperation in the db between 32-bit and 64-bit sections... + */ + writeElfSectionsQuery += + "INSERT INTO elf_sections" + "(name, elf, type, flags, address, file_offset, size, link, info, address_alignment, entry_size ) " + "VALUES("; + writeElfSectionsQuery += std::to_string(elf32Section.sh_name); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(inElf.getId()); + + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf32Section.sh_type); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf32Section.sh_flags); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf32Section.sh_addr); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf32Section.sh_offset); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf32Section.sh_size); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf32Section.sh_link); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf32Section.sh_info); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf32Section.sh_addralign); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf32Section.sh_entsize); + + writeElfSectionsQuery += ");"; + + logger.logDebug("Sending \"%s\" query to database.", writeElfSectionsQuery.c_str()); + + rc = sqlite3_exec(database, writeElfSectionsQuery.c_str(), NULL, NULL, &errorMessage); - /** - *@todo Not sure if I should make a seperation in the db between 32-bit and 64-bit sections... - */ - writeElfSectionsQuery += - "INSERT INTO elf_sections" - "(name, elf, type, flags, address, file_offset, size, link, info, address_alignment, entry_size ) " - "VALUES("; - // writeElfSectionsQuery += "\""; - writeElfSectionsQuery += std::to_string(elf32Section.sh_name); - // writeElfSectionsQuery += "\""; - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(inElf.getId()); - - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(elf32Section.sh_type); - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(elf32Section.sh_flags); - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(elf32Section.sh_addr); - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(elf32Section.sh_offset); - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(elf32Section.sh_size); - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(elf32Section.sh_link); - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(elf32Section.sh_info); - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(elf32Section.sh_addralign); - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(elf32Section.sh_entsize); - - writeElfSectionsQuery += ");"; - - logger.logDebug("Sending \"%s\" query to database.", writeElfSectionsQuery.c_str()); - - rc = sqlite3_exec(database, writeElfSectionsQuery.c_str(), NULL, NULL, &errorMessage); + if (SQLITE_OK == rc) + { + logger.logDebug( + "Variable values were written to the variables schema with " + "SQLITE_OK status."); + } + else + { + if (sqlite3_extended_errcode(database) == SQLITE_CONSTRAINT_UNIQUE) + { + logger.logDebug("%s.", errorMessage); + rc = SQLITE_OK; + } + else + { + logger.logDebug("There was an error while writing data to the variables table."); + logger.logDebug("%s.", errorMessage); + rc = SQLITEDB_ERROR; + } + } + } - if (SQLITE_OK == rc) - { - logger.logDebug( - "Variable values were written to the variables schema with " - "SQLITE_OK status."); + break; } - else + case ELFCLASS64: { - if (sqlite3_extended_errcode(database) == SQLITE_CONSTRAINT_UNIQUE) - { - logger.logDebug("%s.", errorMessage); - rc = SQLITE_OK; - } - else + for (auto elf64Section : inElf.getElf64Headers()) { - logger.logDebug("There was an error while writing data to the variables table."); - logger.logDebug("%s.", errorMessage); - rc = SQLITEDB_ERROR; + inElf.getInitializedSymbolData(); + + /* + * @todo I want to store these SQLite magical values into MACROS, + * but I'm not sure what is the best way to do that without it being + * messy. + */ + std::string writeElfSectionsQuery{}; + + /** + *@todo Not sure if I should make a seperation in the db between 32-bit and 64-bit sections... + */ + writeElfSectionsQuery += + "INSERT INTO elf_sections" + "(name, elf, type, flags, address, file_offset, size, link, info, address_alignment, entry_size ) " + "VALUES("; + writeElfSectionsQuery += std::to_string(elf64Section.sh_name); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(inElf.getId()); + + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf64Section.sh_type); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf64Section.sh_flags); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf64Section.sh_addr); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf64Section.sh_offset); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf64Section.sh_size); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf64Section.sh_link); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf64Section.sh_info); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf64Section.sh_addralign); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf64Section.sh_entsize); + + writeElfSectionsQuery += ");"; + + logger.logDebug("Sending \"%s\" query to database.", writeElfSectionsQuery.c_str()); + + rc = sqlite3_exec(database, writeElfSectionsQuery.c_str(), NULL, NULL, &errorMessage); + + if (SQLITE_OK == rc) + { + logger.logDebug( + "Variable values were written to the variables schema with " + "SQLITE_OK status."); + } + else + { + if (sqlite3_extended_errcode(database) == SQLITE_CONSTRAINT_UNIQUE) + { + logger.logDebug("%s.", errorMessage); + rc = SQLITE_OK; + } + else + { + logger.logDebug("There was an error while writing data to the variables table."); + logger.logDebug("%s.", errorMessage); + rc = SQLITEDB_ERROR; + } + } } + + break; } } @@ -727,73 +859,145 @@ int SQLiteDB::writeElfSymboltableSymbolsToDatabase(ElfFile& inElf) int rc = SQLITEDB_OK; char* errorMessage = NULL; - for (auto elf32Symbol : inElf.getElf32SymbolTable()) + switch (inElf.getElfClass()) { - // std::string symbolInitializedDataName = symbolDataPair.first; - // std::vector symbolInitializedData = symbolDataPair.second; - - inElf.getInitializedSymbolData(); - uint32_t typeID; + case ELFCLASS32: + { + for (auto elf32Symbol : inElf.getElf32SymbolTable()) + { + inElf.getInitializedSymbolData(); - /* - * @todo I want to store these SQLite magical values into MACROS, - * but I'm not sure what is the best way to do that without it being - * messy. - */ - std::string writeElfSectionsQuery{}; + /* + * @todo I want to store these SQLite magical values into MACROS, + * but I'm not sure what is the best way to do that without it being + * messy. + */ + std::string writeElfSectionsQuery{}; - /** - *@todo Not sure if I should make a seperation in the db between 32-bit and 64-bit sections... - */ - writeElfSectionsQuery += - "INSERT INTO elf_symbol_table" - "(name, elf, value, size, info, other, section_index, file_offset, string_table_file_offset ) " - "VALUES("; - // writeElfSectionsQuery += "\""; - writeElfSectionsQuery += std::to_string(elf32Symbol.getSymbol().st_name); - // writeElfSectionsQuery += "\""; - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(inElf.getId()); - - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(elf32Symbol.getSymbol().st_value); - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(elf32Symbol.getSymbol().st_size); - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(elf32Symbol.getSymbol().st_info); - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(elf32Symbol.getSymbol().st_other); - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(elf32Symbol.getSymbol().st_shndx); - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(elf32Symbol.getFileOffset()); - writeElfSectionsQuery += ","; - writeElfSectionsQuery += std::to_string(elf32Symbol.getStrTableFileOffset()); - writeElfSectionsQuery += ");"; - - logger.logDebug("Sending \"%s\" query to database.", writeElfSectionsQuery.c_str()); - - rc = sqlite3_exec(database, writeElfSectionsQuery.c_str(), NULL, NULL, &errorMessage); + /** + *@todo Not sure if I should make a seperation in the db between 32-bit and 64-bit sections... + */ + writeElfSectionsQuery += + "INSERT INTO elf_symbol_table" + "(name, elf, value, size, info, other, section_index, file_offset, string_table_file_offset ) " + "VALUES("; + // writeElfSectionsQuery += "\""; + writeElfSectionsQuery += std::to_string(elf32Symbol.getSymbol().st_name); + // writeElfSectionsQuery += "\""; + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(inElf.getId()); + + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf32Symbol.getSymbol().st_value); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf32Symbol.getSymbol().st_size); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf32Symbol.getSymbol().st_info); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf32Symbol.getSymbol().st_other); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf32Symbol.getSymbol().st_shndx); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf32Symbol.getFileOffset()); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf32Symbol.getStrTableFileOffset()); + writeElfSectionsQuery += ");"; + + logger.logDebug("Sending \"%s\" query to database.", writeElfSectionsQuery.c_str()); + + rc = sqlite3_exec(database, writeElfSectionsQuery.c_str(), NULL, NULL, &errorMessage); - if (SQLITE_OK == rc) - { - logger.logDebug( - "Variable values were written to the variables schema with " - "SQLITE_OK status."); + if (SQLITE_OK == rc) + { + logger.logDebug( + "Variable values were written to the variables schema with " + "SQLITE_OK status."); + } + else + { + if (sqlite3_extended_errcode(database) == SQLITE_CONSTRAINT_UNIQUE) + { + logger.logDebug("%s.", errorMessage); + rc = SQLITE_OK; + } + else + { + logger.logDebug("There was an error while writing data to the variables table."); + logger.logDebug("%s.", errorMessage); + rc = SQLITEDB_ERROR; + } + } + } + break; } - else + case ELFCLASS64: { - if (sqlite3_extended_errcode(database) == SQLITE_CONSTRAINT_UNIQUE) + for (auto elf64Symbol : inElf.getElf64SymbolTable()) { - logger.logDebug("%s.", errorMessage); - rc = SQLITE_OK; - } - else - { - logger.logDebug("There was an error while writing data to the variables table."); - logger.logDebug("%s.", errorMessage); - rc = SQLITEDB_ERROR; + inElf.getInitializedSymbolData(); + + /* + * @todo I want to store these SQLite magical values into MACROS, + * but I'm not sure what is the best way to do that without it being + * messy. + */ + std::string writeElfSectionsQuery{}; + + /** + *@todo Not sure if I should make a seperation in the db between 32-bit and 64-bit sections... + */ + writeElfSectionsQuery += + "INSERT INTO elf_symbol_table" + "(name, elf, value, size, info, other, section_index, file_offset, string_table_file_offset ) " + "VALUES("; + // writeElfSectionsQuery += "\""; + writeElfSectionsQuery += std::to_string(elf64Symbol.getSymbol().st_name); + // writeElfSectionsQuery += "\""; + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(inElf.getId()); + + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf64Symbol.getSymbol().st_value); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf64Symbol.getSymbol().st_size); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf64Symbol.getSymbol().st_info); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf64Symbol.getSymbol().st_other); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf64Symbol.getSymbol().st_shndx); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf64Symbol.getFileOffset()); + writeElfSectionsQuery += ","; + writeElfSectionsQuery += std::to_string(elf64Symbol.getStrTableFileOffset()); + writeElfSectionsQuery += ");"; + + logger.logDebug("Sending \"%s\" query to database.", writeElfSectionsQuery.c_str()); + + rc = sqlite3_exec(database, writeElfSectionsQuery.c_str(), NULL, NULL, &errorMessage); + + if (SQLITE_OK == rc) + { + logger.logDebug( + "Variable values were written to the variables schema with " + "SQLITE_OK status."); + } + else + { + if (sqlite3_extended_errcode(database) == SQLITE_CONSTRAINT_UNIQUE) + { + logger.logDebug("%s.", errorMessage); + rc = SQLITE_OK; + } + else + { + logger.logDebug("There was an error while writing data to the variables table."); + logger.logDebug("%s.", errorMessage); + rc = SQLITEDB_ERROR; + } + } } + break; } } @@ -975,29 +1179,134 @@ int SQLiteDB::writeSymbolsToDatabase(ElfFile& inElf) */ std::string writeSymbolQuery{}; - writeSymbolQuery += - "INSERT INTO symbols(elf, name, byte_size, artifact, long_description, short_description) " - "VALUES("; - writeSymbolQuery += std::to_string(symbol->getElf().getId()); - writeSymbolQuery += ",\""; - writeSymbolQuery += symbol->getName(); + if (!symbol->hasEncoding()) + { + writeSymbolQuery += + "INSERT INTO symbols(elf, name, byte_size, artifact, long_description, short_description) " + "VALUES("; + writeSymbolQuery += std::to_string(symbol->getElf().getId()); + writeSymbolQuery += ",\""; + writeSymbolQuery += symbol->getName(); - writeSymbolQuery += "\","; - writeSymbolQuery += std::to_string(symbol->getByteSize()); - writeSymbolQuery += ","; - writeSymbolQuery += std::to_string(symbol->getArtifact().getId()); + writeSymbolQuery += "\","; + writeSymbolQuery += std::to_string(symbol->getByteSize()); + writeSymbolQuery += ","; + writeSymbolQuery += std::to_string(symbol->getArtifact().getId()); - writeSymbolQuery += ",\""; - writeSymbolQuery += symbol->getLongDescription(); + writeSymbolQuery += ",\""; + writeSymbolQuery += symbol->getLongDescription(); - writeSymbolQuery += "\","; + writeSymbolQuery += "\","; - writeSymbolQuery += "\""; - writeSymbolQuery += symbol->getShortDescription(); + writeSymbolQuery += "\""; + writeSymbolQuery += symbol->getShortDescription(); + + writeSymbolQuery += "\""; + + writeSymbolQuery += ")"; + + rc = sqlite3_exec(database, writeSymbolQuery.c_str(), NULL, NULL, &errorMessage); + + if (SQLITE_OK == rc) + { + logger.logDebug( + "Symbol values were written to the symbols schema with " + "SQLITE_OK status."); + + /*Write the id to this symbol so that other tables can use it as + *a foreign key */ + sqlite3_int64 lastRowId = sqlite3_last_insert_rowid(database); + + symbol->setId(lastRowId); + } + else + { + logger.logError( + "Looks like something went wrong with query " + "\"%s\":\"%s\"", + writeSymbolQuery, errorMessage); + } + } + + else + { + writeSymbolQuery += + "INSERT INTO symbols(elf, name, byte_size, encoding, artifact, long_description, short_description) " + "VALUES("; + writeSymbolQuery += std::to_string(symbol->getElf().getId()); + writeSymbolQuery += ",\""; + writeSymbolQuery += symbol->getName(); + + writeSymbolQuery += "\","; + writeSymbolQuery += std::to_string(symbol->getByteSize()); + writeSymbolQuery += ","; + + writeSymbolQuery += "\""; + writeSymbolQuery += std::to_string(symbol->getElf().getDWARFEncoding(symbol->getEncoding()).getId()); + // writeSymbolQuery += "-47"; + writeSymbolQuery += "\","; + + writeSymbolQuery += std::to_string(symbol->getArtifact().getId()); + + writeSymbolQuery += ",\""; + writeSymbolQuery += symbol->getLongDescription(); + + writeSymbolQuery += "\","; + + writeSymbolQuery += "\""; + writeSymbolQuery += symbol->getShortDescription(); + + writeSymbolQuery += "\""; + + writeSymbolQuery += ")"; + + rc = sqlite3_exec(database, writeSymbolQuery.c_str(), NULL, NULL, &errorMessage); + + if (SQLITE_OK == rc) + { + logger.logDebug( + "Symbol values were written to the symbols schema with " + "SQLITE_OK status."); + + /*Write the id to this symbol so that other tables can use it as + *a foreign key */ + sqlite3_int64 lastRowId = sqlite3_last_insert_rowid(database); + + symbol->setId(lastRowId); + } + else + { + logger.logError( + "Looks like something went wrong with query " + "\"%s\":\"%s\"", + writeSymbolQuery, errorMessage); + } + } + } + } + + // Add symbol to target_symbol mappings to database + for (auto&& symbol : inElf.getSymbols()) + { + if (symbol->hasTargetSymbol()) + { + /* + * @todo I want to store these SQLite magical values into MACROS, + * but I'm not sure what is the best way to do that without it being + * messy. + */ + std::string writeSymbolQuery{}; + writeSymbolQuery += "UPDATE symbols SET target_symbol = "; writeSymbolQuery += "\""; + writeSymbolQuery += std::to_string(symbol->getTargetSymbol()->getId()); + writeSymbolQuery += "\""; + + writeSymbolQuery += " WHERE id = "; - writeSymbolQuery += ")"; + writeSymbolQuery += "\""; + writeSymbolQuery += std::to_string(symbol->getId()); + writeSymbolQuery += "\""; rc = sqlite3_exec(database, writeSymbolQuery.c_str(), NULL, NULL, &errorMessage); @@ -1006,12 +1315,6 @@ int SQLiteDB::writeSymbolsToDatabase(ElfFile& inElf) logger.logDebug( "Symbol values were written to the symbols schema with " "SQLITE_OK status."); - - /*Write the id to this symbol so that other tables can use it as - *a foreign key */ - sqlite3_int64 lastRowId = sqlite3_last_insert_rowid(database); - - symbol->setId(lastRowId); } else { @@ -1275,6 +1578,239 @@ int SQLiteDB::writeEnumerationsToDatabase(ElfFile& inElf) return rc; } +int SQLiteDB::writeEncodingsToDatabase(ElfFile& inElf) +{ + int rc = SQLITEDB_OK; + + std::vector dwarfEncodings = inElf.getDWARFEncodings(); + + if (!doEncodingsExist()) + { + for (Encoding encoding : dwarfEncodings) + { + // Create a SQL statement with placeholders + sqlite3_stmt* stmt; + const char* sql = "INSERT INTO encodings (encoding) VALUES (?);"; + + // Prepare the SQL statement + rc = sqlite3_prepare_v2(database, sql, -1, &stmt, NULL); + + if (rc != SQLITE_OK) + { + std::cerr << "SQL error: " << sqlite3_errmsg(database) << std::endl; + } + else + { + // Bind values to placeholders + sqlite3_bind_text(stmt, 1, encoding.getName().c_str(), -1, SQLITE_STATIC); + + rc = sqlite3_step(stmt); + + // Execute the SQL statement + if (rc != SQLITE_DONE) + { + const char* errorMessage = sqlite3_errmsg(database); + if (SQLITE_OK == rc) + { + logger.logDebug( + "Elf values were written to the encodings schema with " + "SQLITE_OK status."); + } + else + { + if (sqlite3_extended_errcode(database) == SQLITE_CONSTRAINT_UNIQUE) + { + logger.logDebug("%s.", errorMessage); + rc = SQLITE_OK; + } + else + { + logger.logDebug("There was an error while writing data to the encodings table."); + logger.logDebug("%s.", errorMessage); + rc = SQLITEDB_ERROR; + } + } + } + + // Finalize the statement + rc = sqlite3_finalize(stmt); + if (rc != SQLITE_OK) + { + logger.logDebug("There was an error while finalizing the sql statement for encodings table."); + } + else + { + sqlite3_int64 lastRowId = sqlite3_last_insert_rowid(database); + + if (encoding.getName() == "DW_ATE_address") + { + inElf.getDWARFEncoding(DW_ATE_address).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_boolean") + { + inElf.getDWARFEncoding(DW_ATE_boolean).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_complex_float") + { + inElf.getDWARFEncoding(DW_ATE_complex_float).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_float") + { + inElf.getDWARFEncoding(DW_ATE_float).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_signed") + { + inElf.getDWARFEncoding(DW_ATE_signed).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_unsigned") + { + inElf.getDWARFEncoding(DW_ATE_unsigned).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_signed_char") + { + inElf.getDWARFEncoding(DW_ATE_signed_char).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_unsigned_char") + { + inElf.getDWARFEncoding(DW_ATE_unsigned_char).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_imaginary_float") + { + inElf.getDWARFEncoding(DW_ATE_imaginary_float).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_packed_decimal") + { + inElf.getDWARFEncoding(DW_ATE_packed_decimal).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_numeric_string") + { + inElf.getDWARFEncoding(DW_ATE_numeric_string).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_edited") + { + inElf.getDWARFEncoding(DW_ATE_edited).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_signed_fixed") + { + inElf.getDWARFEncoding(DW_ATE_signed_fixed).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_unsigned_fixed") + { + inElf.getDWARFEncoding(DW_ATE_unsigned_fixed).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_decimal_float") + { + inElf.getDWARFEncoding(DW_ATE_decimal_float).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_UCS") + { + inElf.getDWARFEncoding(DW_ATE_UCS).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_ASCII") + { + inElf.getDWARFEncoding(DW_ATE_ASCII).setId(lastRowId); + } + } + } + } + } + else + { + std::map> symbolsMap{}; + + std::string getSymbolIdQuery{"SELECT * FROM encodings;"}; + + char* errorMessage; + + rc = sqlite3_exec(database, getSymbolIdQuery.c_str(), SQLiteDB::selectCallback, &symbolsMap, &errorMessage); + + if (SQLITE_OK == rc) + { + /** + * We know there is only one element in our map, since symbol names are unique. + */ + for (auto pair : symbolsMap) + { + // symbol->setId(std::stoi(pair.first)); + + Encoding encoding{pair.second.at(0)}; + + sqlite3_int64 lastRowId = std::stoi(pair.first); + + if (encoding.getName() == "DW_ATE_address") + { + inElf.getDWARFEncoding(DW_ATE_address).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_boolean") + { + inElf.getDWARFEncoding(DW_ATE_boolean).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_complex_float") + { + inElf.getDWARFEncoding(DW_ATE_complex_float).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_float") + { + inElf.getDWARFEncoding(DW_ATE_float).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_signed") + { + inElf.getDWARFEncoding(DW_ATE_signed).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_unsigned") + { + inElf.getDWARFEncoding(DW_ATE_unsigned).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_signed_char") + { + inElf.getDWARFEncoding(DW_ATE_signed_char).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_unsigned_char") + { + inElf.getDWARFEncoding(DW_ATE_unsigned_char).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_imaginary_float") + { + inElf.getDWARFEncoding(DW_ATE_imaginary_float).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_packed_decimal") + { + inElf.getDWARFEncoding(DW_ATE_packed_decimal).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_numeric_string") + { + inElf.getDWARFEncoding(DW_ATE_numeric_string).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_edited") + { + inElf.getDWARFEncoding(DW_ATE_edited).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_signed_fixed") + { + inElf.getDWARFEncoding(DW_ATE_signed_fixed).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_unsigned_fixed") + { + inElf.getDWARFEncoding(DW_ATE_unsigned_fixed).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_decimal_float") + { + inElf.getDWARFEncoding(DW_ATE_decimal_float).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_UCS") + { + inElf.getDWARFEncoding(DW_ATE_UCS).setId(lastRowId); + } + else if (encoding.getName() == "DW_ATE_ASCII") + { + inElf.getDWARFEncoding(DW_ATE_ASCII).setId(lastRowId); + } + } + } + } + return rc; +} + /** *@brief This method creates all of the schemas that will be needed to store *the DWARF and ELF data. @@ -1356,8 +1892,22 @@ int SQLiteDB::createSchemas(void) if (SQLITE_OK == rc) { logger.logDebug( - "createElfSectionsSchema() created the variables schema " + "createElfSymbolTableSchema() created the variables schema " "successfully."); + + rc = createEncodingsTableSchema(); + + if (SQLITE_OK == rc) + { + logger.logDebug( + "createEncodingsTableSchema() created the variables schema " + "successfully."); + } + else + { + logger.logDebug("createEncodingsTableSchema() failed."); + rc = SQLITEDB_ERROR; + } } else { @@ -1748,3 +2298,27 @@ int SQLiteDB::createElfSymbolTableSchema(void) return rc; } + +int SQLiteDB::createEncodingsTableSchema(void) +{ + std::string createEncodingsTableQuery{CREATE_ENCODINGS_TABLE}; + + int rc = SQLITE_OK; + + /*@todo The last argument for sqlite3_exec is an error handler that is not + * necessary to pass in, but I really think we should for better error + * logging.*/ + rc = sqlite3_exec(database, createEncodingsTableQuery.c_str(), NULL, NULL, NULL); + + if (SQLITE_OK == rc) + { + logger.logDebug("Created table \"artifacts\" with OK status"); + } + else + { + logger.logError("Failed to create the artifacts table. '%s'", sqlite3_errmsg(database)); + rc = SQLITEDB_ERROR; + } + + return rc; +} diff --git a/src/SQLiteDB.h b/src/SQLiteDB.h index be28691e..2cea08cb 100644 --- a/src/SQLiteDB.h +++ b/src/SQLiteDB.h @@ -40,10 +40,14 @@ name TEXT UNIQUE NOT NULL,\ byte_size INTEGER NOT NULL,\ artifact INTEGER,\ + target_symbol INTEGER,\ + encoding 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)\ UNIQUE(name));" #define CREATE_DIMENSION_TABLE \ @@ -146,6 +150,12 @@ FOREIGN KEY (elf) REFERENCES elfs(id),\ UNIQUE (name, type, elf));" +#define CREATE_ENCODINGS_TABLE \ + "CREATE TABLE IF NOT EXISTS encodings(\ + id INTEGER PRIMARY KEY,\ + encoding TEXT NOT NULL,\ + UNIQUE (encoding));" + //#define CREATE_DATA_OBJECTS_TABLE \ // "CREATE TABLE IF NOT EXISTS data_objects(\ // id INTEGER PRIMARY KEY,\ @@ -183,6 +193,7 @@ class SQLiteDB : public IDataContainer int createVariablesSchema(void); int createElfSectionsSchema(void); int createElfSymbolTableSchema(void); + int createEncodingsTableSchema(void); int writeElfToDatabase(ElfFile &inModule); int writeMacrosToDatabase(ElfFile &inModule); int writeVariablesToDatabase(ElfFile &inModule); @@ -193,10 +204,13 @@ class SQLiteDB : public IDataContainer int writeFieldsToDatabase(ElfFile &inModule); int writeEnumerationsToDatabase(ElfFile &inModule); int writeDimensionsListToDatabase(ElfFile &inElf); + int writeEncodingsToDatabase(ElfFile &inElf); static int doesRowExistCallback(void *veryUsed, int argc, char **argv, char **azColName); bool doesSymbolExist(std::string name); bool doesArtifactExist(std::string name); + bool doEncodingsExist(); + public: SQLiteDB(); int initialize(std::string &initString); diff --git a/src/Symbol.cpp b/src/Symbol.cpp index 3b1d1512..a96805ae 100644 --- a/src/Symbol.cpp +++ b/src/Symbol.cpp @@ -170,31 +170,6 @@ bool Symbol::isFieldUnique(std::string& name) return rc; } - -bool Symbol::hasFields(void) -{ - bool rc = false; - - if (fields.size() > 0) - { - rc = true; - } - - return rc; -} - -bool Symbol::isEnumerated(void) -{ - bool rc = false; - - if (enumerations.size() > 0) - { - rc = true; - } - - return rc; -} - /** *@brief Checks if this symbol has any fields that are bitfields. * @@ -217,3 +192,30 @@ bool Symbol::hasBitFields(void) } Artifact& Symbol::getArtifact() { return artifact; } + +/** + * @brief Symbol::setTargetSymbol + * @note Might make sense to use std:optional for targetSymbol, however need to upgrade to C++17 first. + * @param newTargetSymbol + */ +void Symbol::setTargetSymbol(Symbol* newTargetSymbol) { targetSymbol = newTargetSymbol; } + +/** + * @brief Symbol::hasTargetSymbol + * If this function returns false, then + * that means this is the concrete symbol not a typdef'd(aliased) symbol. + */ +bool Symbol::hasTargetSymbol() { return targetSymbol != nullptr; } + +Symbol* Symbol::getTargetSymbol() { return targetSymbol; } + +/** + * @brief Symbol::setEncoding + * @param newEncoding an integer which is one of the values specified in + * in dwarf.h or in DWARF5 specification document section 5.1.1 titled "Base Type Encodings" + */ +void Symbol::setEncoding(int newEncoding) { encoding = newEncoding; } + +bool Symbol::hasEncoding() { return encoding != -1; } + +int Symbol::getEncoding() { return encoding; } diff --git a/src/Symbol.h b/src/Symbol.h index 6b664832..2d8c1807 100644 --- a/src/Symbol.h +++ b/src/Symbol.h @@ -16,6 +16,7 @@ #include "Artifact.h" #include "DimensionList.h" #include "ElfFile.h" +#include "Encoding.h" #include "Enumeration.h" #include "Field.h" #include "Logger.h" @@ -24,11 +25,16 @@ class Field; class Enumeration; class ElfFile; +/** + *@class Symbol represents a "symbol" in the dwarf. + *These include intrinsic types and struct types. + */ class Symbol { public: Symbol(ElfFile &elf); Symbol(ElfFile &elf, std::string &name, uint32_t byte_size, Artifact); + Symbol(ElfFile &elf, std::string &name, uint32_t byte_size, Artifact, Symbol &targetSymbol); virtual ~Symbol(); const std::string &getName(void) const; void setName(std::string &name); @@ -49,14 +55,24 @@ class Symbol bool hasBitFields(); bool isFieldUnique(std::string &name); Field *getField(std::string &name) const; - bool hasFields(void); - bool isEnumerated(void); Artifact &getArtifact(); const std::string &getShortDescription() const { return short_description; } const std::string &getLongDescription() const { return long_description; } + void setTargetSymbol(Symbol *newTargetSymbol); + + Symbol *getTargetSymbol(); + + bool hasTargetSymbol(); + + void setEncoding(int newEncoding); + + bool hasEncoding(); + + int getEncoding(); + private: ElfFile &elf; std::string name; @@ -66,9 +82,12 @@ class Symbol std::vector> fields; std::vector> enumerations; Artifact artifact; + Symbol *targetSymbol{nullptr}; // This is useful for typedef'd names std::string short_description; std::string long_description; + + int encoding{-1}; }; #endif /* SYMBOL_H_ */ diff --git a/src/YAMCS.cpp b/src/YAMCS.cpp deleted file mode 100644 index 305ab3cc..00000000 --- a/src/YAMCS.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name Windhover Labs nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ - -#include "YAMCS.h" - -YAMCS::YAMCS() -{ - // TODO Auto-generated constructor stub -} - -YAMCS::~YAMCS() -{ - // TODO Auto-generated destructor stub -} diff --git a/src/YAMCS.h b/src/YAMCS.h deleted file mode 100644 index 12b22a87..00000000 --- a/src/YAMCS.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2017 Windhover Labs, L.L.C. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name Windhover Labs nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ - -#ifndef YAMCS_H_ -#define YAMCS_H_ - -class YAMCS -{ - public: - YAMCS(); - virtual ~YAMCS(); -}; - -#endif /* YAMCS_H_ */ diff --git a/src/main.cpp b/src/main.cpp index b8407536..bb136a24 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -56,7 +56,7 @@ static char doc[] = /* A description of the arguments we accept. */ static char args_doc[] = "--input --mode (--output | " - "(--address --port --project )) -x"; + "(--address --port --project )) -x -g"; /* The options we understand. */ static struct argp_option options[] = {{"input", 'i', "FILE", 0, "Input ELF file"}, @@ -74,6 +74,10 @@ static struct argp_option options[] = {{"input", 'i', "FILE", 0, "Input ELF file {"extras", 'x', NULL, 0, "Extra DWARF and ELF data such as variables. Enabling this" "will cause juicer to take longer."}, + {"groupNumber", 'g', "group", 0, + "Group number to extract data forom inside of DWARF section." + "Useful for situations where debug sections (eg. debug_macros) are spreadout through different groups." + " An example of this is when macros are split in different groups by gcc for unlinked ELF object files."}, {0}}; /* Used by main to communicate with parse_opt. */ @@ -99,6 +103,7 @@ typedef struct char *project; bool project_set; bool extras; + int groupNumber; } arguments_t; /* Parse a single option. */ @@ -180,6 +185,22 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) break; } + case 'g': + { + for (int i = 0; i < strlen(arg); i++) + { + if (isdigit(arg[i]) == 0) + { + printf("Error: group number MUST be a number"); + argp_usage(state); + return ARGP_KEY_ERROR; + } + } + + arguments->groupNumber = atoi(arg); + break; + } + case ARGP_KEY_ARG: { // if (state->arg_num >= 2) @@ -285,13 +306,13 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) } } - // /* Verify Extras. */ - // if (arguments->extras) - // { - // // printf("Error: extras name must be set.\n"); - // // argp_usage(state); - // return ARGP_KEY_ERROR; - // } + /* Verify group number. */ + if (arguments->groupNumber < 0) + { + printf("Error: Group number must be 0 or greater.\n"); + argp_usage(state); + return ARGP_KEY_ERROR; + } break; } @@ -305,11 +326,8 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) return 0; } -TestStructA_t testStructA2 = {}; -TestStructB_t testStructB2 = {}; - /* Our argp parser. */ -static struct argp argp = {options, parse_opt, args_doc, doc}; +static struct argp argp = {options, parse_opt, args_doc, doc}; int main(int argc, char **argv) { @@ -318,16 +336,18 @@ int main(int argc, char **argv) /* Set argument default values. */ memset(&arguments, 0, sizeof(arguments)); - arguments.verbosity = 1; - arguments.extras = false; + arguments.verbosity = 1; + arguments.extras = false; + arguments.groupNumber = 0; /* Parse our arguments; every option seen by parse_opt will be reflected in arguments. */ - parse_error = argp_parse(&argp, argc, argv, 0, 0, &arguments); + parse_error = argp_parse(&argp, argc, argv, 0, 0, &arguments); if (parse_error == 0) { Juicer juicer; juicer.setExtras(arguments.extras); + juicer.setGroupNumber(arguments.groupNumber); IDataContainer *idc = 0; Logger logger = Logger(arguments.verbosity); diff --git a/unit-test/TestElfFile.cpp b/unit-test/TestElfFile.cpp index 4e5bdc8a..973a8028 100644 --- a/unit-test/TestElfFile.cpp +++ b/unit-test/TestElfFile.cpp @@ -5,16 +5,17 @@ * Author: vagrant */ -#include "../src/ElfFile.h" -#include "catch.hpp" #include +#include "../src/ElfFile.h" +#include "catch.hpp" /** *@todo This testing module is not done yet. */ -TEST_CASE( "Correctness of a Module object instance", "[Module] " ) { +TEST_CASE("Correctness of a Module object instance", "[Module] ") +{ std::string newElfName{"ABC"}; uint32_t elfId = 102; ElfFile myElf{newElfName}; @@ -25,11 +26,6 @@ TEST_CASE( "Correctness of a Module object instance", "[Module] " ) { newElfName.insert(0, resolvedPath); myElf.setId(elfId); - REQUIRE( myElf.getName() == newElfName ); - REQUIRE( myElf.getId() == elfId ); - + REQUIRE(myElf.getName() == newElfName); + REQUIRE(myElf.getId() == elfId); } - - - - diff --git a/unit-test/TestEnumeration.cpp b/unit-test/TestEnumeration.cpp index 8e5a4533..96498d94 100644 --- a/unit-test/TestEnumeration.cpp +++ b/unit-test/TestEnumeration.cpp @@ -4,8 +4,8 @@ * Created on: Aug 12, 2020 * Author: vagrant */ -#include "catch.hpp" #include "Enumeration.h" +#include "catch.hpp" /** * @brief Unit tests for Enumeration class. @@ -16,9 +16,9 @@ TEST_CASE("Test Enumeration name correctness", "[Enumeration]") std::string symbolName{"string"}; std::string elfName{"ABC"}; - ElfFile symbolModule{elfName}; + ElfFile symbolModule{elfName}; - Symbol enumSymbol{symbolModule}; + Symbol enumSymbol{symbolModule}; enumSymbol.setName(symbolName); std::string colorName{"Color"}; @@ -34,11 +34,11 @@ TEST_CASE("Test Enumeration value correctness", "[Enumeration]") std::string symbolName{"string"}; std::string elfName{"ABC"}; - ElfFile symbolModule{elfName}; + ElfFile symbolModule{elfName}; - Symbol enumSymbol{symbolModule}; + Symbol enumSymbol{symbolModule}; enumSymbol.setName(symbolName); - uint64_t value{714}; + uint64_t value{714}; Enumeration colorEnumeration{enumSymbol}; @@ -47,15 +47,17 @@ TEST_CASE("Test Enumeration value correctness", "[Enumeration]") REQUIRE(colorEnumeration.getValue() == value); } -TEST_CASE("Test Constructor Enumeration(Symbol &symbol) " - " correctness ", "[Enumeration]") +TEST_CASE( + "Test Constructor Enumeration(Symbol &symbol) " + " correctness ", + "[Enumeration]") { std::string symbolName{"string"}; std::string elfName{"ABC"}; - ElfFile symbolModule{elfName}; + ElfFile symbolModule{elfName}; - Symbol enumSymbol{symbolModule}; + Symbol enumSymbol{symbolModule}; enumSymbol.setName(symbolName); Enumeration colorEnumeration{enumSymbol}; @@ -63,17 +65,19 @@ TEST_CASE("Test Constructor Enumeration(Symbol &symbol) " REQUIRE(colorEnumeration.getSymbol().getName() == symbolName); } -TEST_CASE("Test Constructor Enumeration(Symbol &symbol, std::string &name, uint64_t value) " - " correctness ", "[Enumeration]") +TEST_CASE( + "Test Constructor Enumeration(Symbol &symbol, std::string &name, uint64_t value) " + " correctness ", + "[Enumeration]") { std::string symbolName{"string"}; std::string enumName{"Color"}; uint64_t value{714}; std::string elfName{"ABC"}; - ElfFile symbolModule{elfName}; + ElfFile symbolModule{elfName}; - Symbol enumSymbol{symbolModule}; + Symbol enumSymbol{symbolModule}; enumSymbol.setName(symbolName); Enumeration colorEnumeration{enumSymbol, enumName, value}; diff --git a/unit-test/TestIDataContainer.cpp b/unit-test/TestIDataContainer.cpp index fdb21df6..0e011edf 100644 --- a/unit-test/TestIDataContainer.cpp +++ b/unit-test/TestIDataContainer.cpp @@ -5,6 +5,7 @@ * Author: vagrant */ #include + #include "IDataContainer.h" /** diff --git a/unit-test/TestLogger.cpp b/unit-test/TestLogger.cpp index ee0ed84c..65474158 100644 --- a/unit-test/TestLogger.cpp +++ b/unit-test/TestLogger.cpp @@ -4,7 +4,3 @@ * Created on: Aug 21, 2020 * Author: vagrant */ - - - - diff --git a/unit-test/TestSymbol.cpp b/unit-test/TestSymbol.cpp index 6eca635b..574b9fc1 100644 --- a/unit-test/TestSymbol.cpp +++ b/unit-test/TestSymbol.cpp @@ -6,63 +6,65 @@ */ #include -#include "catch.hpp" -#include "Field.h" -#include "Enumeration.h" #include +#include "Enumeration.h" +#include "Field.h" +#include "catch.hpp" + /** *@todo This testing elf is not done yet. */ -TEST_CASE( "Test the correctness of name", "[Symbol]" ) +TEST_CASE("Test the correctness of name", "[Symbol]") { std::string newElfName{"ABC"}; std::string newSymbolName{"string"}; - ElfFile myelf{newElfName}; - Symbol newSymbol{myelf}; + ElfFile myelf{newElfName}; + Symbol newSymbol{myelf}; newSymbol.setName(newSymbolName); REQUIRE(newSymbol.getName() == newSymbolName); } -TEST_CASE( "Test the correctness of byte_size ", "[Symbol]" ) +TEST_CASE("Test the correctness of byte_size ", "[Symbol]") { - std::string newElfName{"ABC"};; - uint32_t byteSize{8}; - ElfFile myelf{newElfName}; - Symbol newSymbol{myelf}; + std::string newElfName{"ABC"}; + ; + uint32_t byteSize{8}; + ElfFile myelf{newElfName}; + Symbol newSymbol{myelf}; newSymbol.setByteSize(byteSize); REQUIRE(newSymbol.getByteSize() == byteSize); } -TEST_CASE( "Test the correctness of id ", "[Symbol]" ) +TEST_CASE("Test the correctness of id ", "[Symbol]") { std::string newElfName{"ABC"}; std::string newSymbolName{"string"}; uint32_t id{123}; - ElfFile myelf{newElfName}; - Symbol newSymbol{myelf}; + ElfFile myelf{newElfName}; + Symbol newSymbol{myelf}; newSymbol.setId(id); REQUIRE(newSymbol.getId() == id); } -TEST_CASE( "Test addField(Field &inField) method", "[Symbol]" ) +TEST_CASE("Test addField(Field &inField) method", "[Symbol]") { - std::string newElfName{"ABC"}; - std::string newSymbolName{"string"}; + std::string newElfName{"ABC"}; + std::string newSymbolName{"string"}; const std::string fieldName{"intField"}; - ElfFile myelf{newElfName}; + ElfFile myelf{newElfName}; - Symbol newSymbol{myelf}; + Symbol newSymbol{myelf}; - Symbol newType{myelf}; + Symbol newType{myelf}; - Field newField{newSymbol, newType}; + Field newField{newSymbol, newType}; newField.setName(fieldName); newSymbol.addField(newField); @@ -70,21 +72,23 @@ TEST_CASE( "Test addField(Field &inField) method", "[Symbol]" ) REQUIRE(newSymbol.getFields().back()->getName() == fieldName); } -TEST_CASE( "Test addField(std::string& inName, uint32_t inByteOffset, " - "Symbol &inType, uint32_t inMultiplicity, " - "bool inLittleEndian) method ", "[Symbol]" ) +TEST_CASE( + "Test addField(std::string& inName, uint32_t inByteOffset, " + "Symbol &inType, uint32_t inMultiplicity, " + "bool inLittleEndian) method ", + "[Symbol]") { - std::string fieldName{"intField"}; - std::string newElfName{"ABC"}; - std::string newSymbolName{"string"}; - std::string newTypeName{"Shape"}; - ElfFile myelf{newElfName}; - bool littleEndian = true; - uint32_t byteOffset{32}; - DimensionList dimList{}; - - Symbol newSymbol{myelf}; - Symbol newType{myelf}; + std::string fieldName{"intField"}; + std::string newElfName{"ABC"}; + std::string newSymbolName{"string"}; + std::string newTypeName{"Shape"}; + ElfFile myelf{newElfName}; + bool littleEndian = true; + uint32_t byteOffset{32}; + DimensionList dimList{}; + + Symbol newSymbol{myelf}; + Symbol newType{myelf}; newType.setName(newTypeName); @@ -93,18 +97,17 @@ TEST_CASE( "Test addField(std::string& inName, uint32_t inByteOffset, " REQUIRE(newSymbol.getFields().back()->getName() == fieldName); REQUIRE(newSymbol.getFields().back()->getByteOffset() == byteOffset); REQUIRE(newSymbol.getFields().back()->getType().getName() == newTypeName); -// REQUIRE(newSymbol.getFields().back()->getDimensionList().size()== dimList.size()); + // REQUIRE(newSymbol.getFields().back()->getDimensionList().size()== dimList.size()); REQUIRE(newSymbol.getFields().back()->isLittleEndian() == littleEndian); } -TEST_CASE( "Test addEnumeration(Enumeration &inEnumeration); method", - "[Symbol]" ) +TEST_CASE("Test addEnumeration(Enumeration &inEnumeration); method", "[Symbol]") { - std::string newElfName{"ABC"}; - std::string newSymbolName{"string"}; - std::string enumName{"Color"}; - ElfFile myelf{newElfName}; - Symbol newSymbol{myelf}; + std::string newElfName{"ABC"}; + std::string newSymbolName{"string"}; + std::string enumName{"Color"}; + ElfFile myelf{newElfName}; + Symbol newSymbol{myelf}; Enumeration newEnum(newSymbol); newEnum.setName(enumName); @@ -114,15 +117,14 @@ TEST_CASE( "Test addEnumeration(Enumeration &inEnumeration); method", REQUIRE(newSymbol.getEnumerations().back()->getName() == enumName); } -TEST_CASE( "Test addEnumeration(std::string& inName, int32_t inValue); method", - "[Symbol]" ) +TEST_CASE("Test addEnumeration(std::string& inName, int32_t inValue); method", "[Symbol]") { - std::string newElfName{"ABC"}; - std::string newSymbolName{"string"}; - std::string enumName{"Color"}; - uint64_t enumValue{589}; - ElfFile myelf{newElfName}; - Symbol newSymbol{myelf}; + std::string newElfName{"ABC"}; + std::string newSymbolName{"string"}; + std::string enumName{"Color"}; + uint64_t enumValue{589}; + ElfFile myelf{newElfName}; + Symbol newSymbol{myelf}; Enumeration newEnum(newSymbol); newEnum.setName(enumName); @@ -133,15 +135,14 @@ TEST_CASE( "Test addEnumeration(std::string& inName, int32_t inValue); method", REQUIRE(newSymbol.getEnumerations().back()->getValue() == enumValue); } -TEST_CASE( "Test getEnumerations() method", - "[Symbol]" ) +TEST_CASE("Test getEnumerations() method", "[Symbol]") { - std::string newElfName{"ABC"}; - std::string newSymbolName{"string"}; - std::string enumName{"Color"}; - uint64_t enumValue{589}; - ElfFile myelf{newElfName}; - Symbol newSymbol{myelf}; + std::string newElfName{"ABC"}; + std::string newSymbolName{"string"}; + std::string enumName{"Color"}; + uint64_t enumValue{589}; + ElfFile myelf{newElfName}; + Symbol newSymbol{myelf}; Enumeration newEnum(newSymbol); newEnum.setName(enumName); @@ -153,36 +154,36 @@ TEST_CASE( "Test getEnumerations() method", REQUIRE(newSymbol.getEnumerations().back()->getValue() == enumValue); } -TEST_CASE( "Test getFields() method", "[Symbol]" ) +TEST_CASE("Test getFields() method", "[Symbol]") { - std::string newElfName{"ABC"}; - std::string newSymbolName{"string"}; + std::string newElfName{"ABC"}; + std::string newSymbolName{"string"}; const std::string fieldName{"intField"}; - ElfFile myelf{newElfName}; + ElfFile myelf{newElfName}; - Symbol newSymbol{myelf}; - Symbol newType{myelf}; + Symbol newSymbol{myelf}; + Symbol newType{myelf}; - Field newField{newSymbol, newType}; + Field newField{newSymbol, newType}; newField.setName(fieldName); newSymbol.addField(newField); - REQUIRE(1 ==newSymbol.getFields().size()); + REQUIRE(1 == newSymbol.getFields().size()); REQUIRE(newSymbol.getFields().back()->getName() == fieldName); } -TEST_CASE( "Test isFieldUnique(std::string &name) method with unique fields", "[Symbol]" ) +TEST_CASE("Test isFieldUnique(std::string &name) method with unique fields", "[Symbol]") { std::string newElfName{"ABC"}; std::string newSymbolName{"string"}; std::string intFieldName{"intField"}; std::string floatFieldName{"floatField"}; - ElfFile myelf{newElfName}; + ElfFile myelf{newElfName}; - Symbol newSymbol{myelf}; - Symbol newType{myelf}; + Symbol newSymbol{myelf}; + Symbol newType{myelf}; - Field newIntField{newSymbol, newType}; + Field newIntField{newSymbol, newType}; newIntField.setName(intFieldName); @@ -194,10 +195,10 @@ TEST_CASE( "Test isFieldUnique(std::string &name) method with unique fields", "[ /** * Test constructors */ -TEST_CASE( "Test the correctness of constructor Symbol(elf &elf) ", "[Symbol]" ) +TEST_CASE("Test the correctness of constructor Symbol(elf &elf) ", "[Symbol]") { std::string newElfName{"ABC"}; - ElfFile myelf{newElfName}; + ElfFile myelf{newElfName}; Symbol newSymbol{myelf}; char resolvedPath[PATH_MAX]; @@ -208,18 +209,19 @@ TEST_CASE( "Test the correctness of constructor Symbol(elf &elf) ", "[Symbol]" ) REQUIRE(newSymbol.getElf().getName() == newElfName); } -TEST_CASE( "Test the correctness of constructor Symbol(elf &elf," - "std::string &name," - "uint32_t byte_size) ", - "[Symbol]" ) +TEST_CASE( + "Test the correctness of constructor Symbol(elf &elf," + "std::string &name," + "uint32_t byte_size) ", + "[Symbol]") { std::string newElfName{"ABC"}; - ElfFile myelf{newElfName}; + ElfFile myelf{newElfName}; std::string symbolName{"string"}; uint32_t byteSize{8}; char resolvedPath[PATH_MAX]; - Symbol newSymbol{myelf, symbolName, byteSize, myelf}; + Symbol newSymbol{myelf, symbolName, byteSize, myelf}; realpath(newElfName.c_str(), resolvedPath); newElfName.clear(); @@ -230,17 +232,17 @@ TEST_CASE( "Test the correctness of constructor Symbol(elf &elf," REQUIRE(newSymbol.getByteSize() == byteSize); } -TEST_CASE( "Test the correctness of constructor Symbol(const Symbol &symbol)", "[Symbol]" ) +TEST_CASE("Test the correctness of constructor Symbol(const Symbol &symbol)", "[Symbol]") { std::string newElfName{"ABC"}; - ElfFile myelf{newElfName}; + ElfFile myelf{newElfName}; std::string symbolName{"string"}; uint32_t byteSize{8}; char resolvedPath[PATH_MAX]; - Symbol copySymbol{myelf, symbolName, byteSize, Artifact{myelf}}; + Symbol copySymbol{myelf, symbolName, byteSize, Artifact{myelf}}; - Symbol constSymbol{copySymbol}; // @suppress("Invalid arguments") + Symbol constSymbol{copySymbol}; // @suppress("Invalid arguments") realpath(newElfName.c_str(), resolvedPath); newElfName.clear(); diff --git a/unit-test/macro_test.cpp b/unit-test/macro_test.cpp new file mode 100644 index 00000000..04b129a2 --- /dev/null +++ b/unit-test/macro_test.cpp @@ -0,0 +1,4 @@ +#define MAC1 2 +#define MAC2 3 +#include "macro_test.h" +#define MAC3 4 \ No newline at end of file diff --git a/unit-test/macro_test.h b/unit-test/macro_test.h new file mode 100644 index 00000000..ffb490f7 --- /dev/null +++ b/unit-test/macro_test.h @@ -0,0 +1,2 @@ +#define MAC4 +#define MAC5 1 \ No newline at end of file diff --git a/unit-test/main.cpp b/unit-test/main.cpp index a7b585c8..bcf84bd2 100644 --- a/unit-test/main.cpp +++ b/unit-test/main.cpp @@ -9,12 +9,11 @@ /*This tells Catch to provide a main() - only do this in one cpp file*/ #define CATCH_CONFIG_MAIN - /**This disables coloring output so that Eclipse CDT(Version: 9.7.0.201903092251) *will be able to render it. If you really like colored output, you'll have to use *something else other than Eclipse's console(such as GNOME shell) to run the tests *and comment out the CATCH_CONFIG_COLOUR_NONE macro. */ -//#define CATCH_CONFIG_COLOUR_NONE +// #define CATCH_CONFIG_COLOUR_NONE #include "catch.hpp" diff --git a/unit-test/main_test.cpp b/unit-test/main_test.cpp index 120cdc60..d4924364 100644 --- a/unit-test/main_test.cpp +++ b/unit-test/main_test.cpp @@ -4,70 +4,74 @@ * Created on: Aug 20, 2020 * Author: vagrant */ -#include "catch.hpp" -#include "Juicer.h" -#include "IDataContainer.h" -#include "SQLiteDB.h" -#include -#include +#include #include #include -#include "test_file1.h" -#include + #include +#include +#include #include +#include "IDataContainer.h" +#include "Juicer.h" +#include "SQLiteDB.h" +#include "catch.hpp" +#include "test_file1.h" /** *These test file locations assumes that the tests are run * with "make run-tests". */ -#define TEST_FILE_1 "ut_obj/test_file1.o" -#define TEST_FILE_2 "ut_obj/test_file2.o" +#define TEST_FILE_1 "ut_obj/test_file1.o" +#define TEST_FILE_2 "ut_obj/test_file2.o" +#define TEST_FILE_3 "ut_obj_32/test_file1.o" + +#define TEST_FILE_4 "ut_obj/macro_test.o" -//DO NOT rename this macro to something like SQLITE_NULL as that is a macro that exists in sqlite3 +// DO NOT rename this macro to something like SQLITE_NULL as that is a macro that exists in sqlite3 #define TEST_NULL_STR "NULL" /** *Checks if the platform is little endian. *This is used as a source of truth for our unit tests. */ -bool is_little_endian() +static bool is_little_endian() { - int n = 1; - return (*(char *)&n == 1); + int n = 1; + return (*(char*)&n == 1); } /** *@brief This callback returns the record inside of a std::vector * */ -static int selectVectorCallback(void *veryUsed, int argc, char **argv, char **azColName) +static int selectVectorCallback(void* veryUsed, int argc, char** argv, char** azColName) { - int i; - auto* tableData = ( std::vector>*)veryUsed; + int i; + auto* tableData = (std::vector>*)veryUsed; - std::vector recordVector{}; + std::vector recordVector{}; - for(i=0; ipush_back(recordVector); - return 0; + tableData->push_back(recordVector); + return 0; } struct columnNameToRowMap { - std::string colName{}; - std::map > recordMap{}; + std::string colName{}; + std::map> recordMap{}; }; /** @@ -85,33 +89,33 @@ struct columnNameToRowMap * * the one and only key to the map is configurable via the colName field of columnNameToRowMap structure. */ -static int selectCallbackUsingCustomColNameAsKey(void *veryUsed, int argc, char **argv, char **azColName) +static int selectCallbackUsingCustomColNameAsKey(void* veryUsed, int argc, char** argv, char** azColName) { - columnNameToRowMap* mappingData = (columnNameToRowMap*) veryUsed; - auto* row = (std::map >*)(&mappingData->recordMap); - int key_index = 0; - std::vector tableData{}; - - for(int i=0; icolName.c_str(), azColName[i]) == 0) - { - key_index = i; - } - tableData.push_back(tempData); - } - - std::string id{argv[key_index]}; - - (*row)[id] = tableData; - - return 0; + columnNameToRowMap* mappingData = (columnNameToRowMap*)veryUsed; + auto* row = (std::map>*)(&mappingData->recordMap); + int key_index = 0; + std::vector tableData{}; + + for (int i = 0; i < argc; i++) + { + std::string tempData{TEST_NULL_STR}; + if (argv[i] != nullptr) + { + tempData.assign(argv[i]); + } + + if (strcmp(mappingData->colName.c_str(), azColName[i]) == 0) + { + key_index = i; + } + tableData.push_back(tempData); + } + + std::string id{argv[key_index]}; + + (*row)[id] = tableData; + + return 0; } /** @@ -135,50 +139,78 @@ static int selectCallbackUsingCustomColNameAsKey(void *veryUsed, int argc, char *[ {"id:" "elf": "1", "name": "char", "byte_size":"1"} ] * */ -static int selectCallbackUsingColNameAsKey(void *veryUsed, int argc, char **argv, char **azColName) +static int selectCallbackUsingColNameAsKey(void* veryUsed, int argc, char** argv, char** azColName) { - auto* allRecords = (std::vector>*) veryUsed; + auto* allRecords = (std::vector>*)veryUsed; - std::map newRecord{}; + std::map newRecord{}; - std::vector tableData{}; + std::vector tableData{}; - for(int i=0; ipush_back(newRecord); + allRecords->push_back(newRecord); - return 0; + return 0; } - -std::string getmd5sumFromSystem(char resolvedPath[PATH_MAX]) { -// TODO:Unfortunately the redirect is adding junk(a "\n" character at the end) at the end of the crc. - std::string MD5CommandStr { "md5sum " }; - MD5CommandStr += resolvedPath; - MD5CommandStr += " >MD5.txt"; - std::system(MD5CommandStr.c_str()); // executes the UNIX command "ls -l >test.txt" - std::strstream expectedMD5 { }; - expectedMD5 << std::ifstream("MD5.txt").rdbuf(); - REQUIRE(remove("./MD5.txt") == 0); - std::string expectedMD5Str { expectedMD5.str() }; +static std::string getmd5sumFromSystem(char resolvedPath[PATH_MAX]) +{ + // TODO:Unfortunately the redirect is adding junk(a "\n" character at the end) at the end of the crc. + std::string MD5CommandStr{"md5sum "}; + MD5CommandStr += resolvedPath; + MD5CommandStr += " >MD5.txt"; + std::system(MD5CommandStr.c_str()); // executes the UNIX command "md5sum resolvedPath[PATH_MAX] >MD5.txt" + std::strstream expectedMD5{}; + expectedMD5 << std::ifstream("MD5.txt").rdbuf(); + REQUIRE(remove("./MD5.txt") == 0); + std::string expectedMD5Str{expectedMD5.str()}; // Size should be size of hash(16 bytes) - expectedMD5Str = expectedMD5Str.substr(0, 32); - REQUIRE(expectedMD5Str.size() == 32); - return expectedMD5Str; + expectedMD5Str = expectedMD5Str.substr(0, 32); + REQUIRE(expectedMD5Str.size() == 32); + return expectedMD5Str; } +static std::map followTargetSymbol(sqlite3* database, std::string symbolID) +{ + std::string symbolQuery{"SELECT * FROM symbols where id="}; + int rc = 0; + + symbolQuery += symbolID; + symbolQuery += ";"; -TEST_CASE("Test Juicer at the highest level with SQLiteDB" ,"[main_test#1]") + std::map targetSymbolRecord{}; + + std::vector> symbolRecords{}; + + char* errorMessage = nullptr; + + rc = sqlite3_exec(database, symbolQuery.c_str(), selectCallbackUsingColNameAsKey, &symbolRecords, &errorMessage); + + REQUIRE(rc == JUICER_OK); + + if (symbolRecords.at(0).at("target_symbol") != "NULL") + { + targetSymbolRecord = followTargetSymbol(database, symbolRecords.at(0).at("target_symbol")); + } + else + { + return symbolRecords.at(0); + } + return targetSymbolRecord; +} + +TEST_CASE("Test Juicer at the highest level with SQLiteDB", "[main_test#1]") { Juicer juicer; IDataContainer* idc = 0; @@ -189,63 +221,86 @@ TEST_CASE("Test Juicer at the highest level with SQLiteDB" ,"[main_test#1]") idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); - REQUIRE(idc!=nullptr); + REQUIRE(idc != nullptr); logger.logInfo("IDataContainer was constructed successfully for unit test."); juicer.setIDC(idc); REQUIRE(juicer.parse(inputFile) == JUICER_OK); + REQUIRE((juicer.getDwarfVersion() == 4 || juicer.getDwarfVersion() == 5)); + /** *Clean up our database handle and objects in memory. */ ((SQLiteDB*)(idc))->close(); - REQUIRE(remove("./test_db.sqlite")==0); + REQUIRE(remove("./test_db.sqlite") == 0); delete idc; - } - -TEST_CASE("Test the correctness of the Circle struct after Juicer has processed it." ,"[main_test#2]") +TEST_CASE("Test the correctness of the Circle struct after Juicer has processed it.", "[main_test#2]") { - /** - * This assumes that the test_file was compiled on - * gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 - * little-endian machine. - */ + /** + * 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; - char* errorMessage = nullptr; - std::string little_endian = is_little_endian()? "1": "0"; + int rc; + char* errorMessage = nullptr; + std::string little_endian = is_little_endian() ? "1" : "0"; logger.logWarning("This is just a test."); std::string inputFile{TEST_FILE_1}; idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); - REQUIRE(idc!=nullptr); + REQUIRE(idc != nullptr); logger.logInfo("IDataContainer was constructed successfully for unit test."); juicer.setIDC(idc); rc = juicer.parse(inputFile); - REQUIRE(rc == JUICER_OK); + REQUIRE((juicer.getDwarfVersion() == 4 || juicer.getDwarfVersion() == 5)); - std::string getCircleStructQuery{"SELECT * FROM symbols WHERE name = \"Circle\"; "}; + REQUIRE(rc == JUICER_OK); - sqlite3 *database; + sqlite3* database; rc = sqlite3_open("./test_db.sqlite", &database); REQUIRE(rc == SQLITE_OK); + std::string getAllEncodings{"SELECT * FROM encodings"}; + + std::vector> encodingsRecords{}; + + rc = sqlite3_exec(database, getAllEncodings.c_str(), selectCallbackUsingColNameAsKey, &encodingsRecords, &errorMessage); + + REQUIRE(rc == SQLITE_OK); + + REQUIRE(encodingsRecords.size() == 18); + + /** + * @brief encodingMap A map of row_id -> encoding. + * i.e {"1":"DW_ATE_address", "2":"DW_ATE_boolean", etc}. Useful for avoiding having to look up the encoding by foreign of a symbol + * every time. + */ + std::map encodingMap{}; + + for (auto encodingRecord : encodingsRecords) + { + encodingMap[encodingRecord["id"]] = encodingRecord["encoding"]; + } + + std::string getCircleStructQuery{"SELECT * FROM symbols WHERE name = \"Circle\"; "}; + std::vector> circleRecords{}; - rc = sqlite3_exec(database, getCircleStructQuery.c_str(), selectCallbackUsingColNameAsKey, &circleRecords, - &errorMessage); + rc = sqlite3_exec(database, getCircleStructQuery.c_str(), selectCallbackUsingColNameAsKey, &circleRecords, &errorMessage); REQUIRE(rc == SQLITE_OK); @@ -254,12 +309,20 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed * Check the correctness of Circle struct. */ - REQUIRE(circleRecords.at(0).find("name") != circleRecords.at(0).end()); - REQUIRE(circleRecords.at(0).find("byte_size") != circleRecords.at(0).end()); - REQUIRE(circleRecords.at(0).find("id") != circleRecords.at(0).end()); + REQUIRE(circleRecords.at(0).find("name") != circleRecords.at(0).end()); + REQUIRE(circleRecords.at(0).find("byte_size") != circleRecords.at(0).end()); + REQUIRE(circleRecords.at(0).find("id") != circleRecords.at(0).end()); + REQUIRE(circleRecords.at(0).find("target_symbol") != circleRecords.at(0).end()); + REQUIRE(circleRecords.at(0).find("encoding") != circleRecords.at(0).end()); + REQUIRE(circleRecords.at(0).find("short_description") != circleRecords.at(0).end()); + REQUIRE(circleRecords.at(0).find("long_description") != circleRecords.at(0).end()); - REQUIRE(circleRecords.at(0)["name"] == "Circle"); - REQUIRE(circleRecords.at(0)["byte_size"] == std::to_string(sizeof(Circle))); + REQUIRE(circleRecords.at(0)["name"] == "Circle"); + REQUIRE(circleRecords.at(0)["byte_size"] == std::to_string(sizeof(Circle))); + REQUIRE(circleRecords.at(0)["target_symbol"] == "NULL"); + REQUIRE(circleRecords.at(0)["encoding"] == "NULL"); + REQUIRE(circleRecords.at(0)["short_description"] == ""); + REQUIRE(circleRecords.at(0)["long_description"] == ""); /** *Check the fields of the Circle struct. @@ -274,30 +337,32 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed std::vector> fieldsRecords{}; - rc = sqlite3_exec(database, getCircleFields.c_str(), selectCallbackUsingColNameAsKey, &fieldsRecords, - &errorMessage); + rc = sqlite3_exec(database, getCircleFields.c_str(), selectCallbackUsingColNameAsKey, &fieldsRecords, &errorMessage); REQUIRE(rc == SQLITE_OK); 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"]); - }); + // 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) + 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"] == "diameter"); @@ -312,20 +377,23 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed std::vector> dimaterSymbolRecords{}; - rc = sqlite3_exec(database, getDiameterType.c_str(), selectCallbackUsingColNameAsKey, &dimaterSymbolRecords, - &errorMessage); + rc = sqlite3_exec(database, getDiameterType.c_str(), selectCallbackUsingColNameAsKey, &dimaterSymbolRecords, &errorMessage); REQUIRE(rc == SQLITE_OK); REQUIRE(dimaterSymbolRecords.size() == 1); - std::string diameterType{dimaterSymbolRecords.at(0).at("id")}; + std::string diameterType{dimaterSymbolRecords.at(0).at("id")}; REQUIRE(fieldsRecords.at(0)["symbol"] == circleRecords.at(0)["id"]); - REQUIRE(fieldsRecords.at(0)["name"] == "diameter"); + REQUIRE(fieldsRecords.at(0)["name"] == "diameter"); REQUIRE(fieldsRecords.at(0)["byte_offset"] == std::to_string(offsetof(Circle, diameter))); REQUIRE(fieldsRecords.at(0)["type"] == diameterType); 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"] == ""); REQUIRE(fieldsRecords.at(1)["name"] == "radius"); @@ -336,18 +404,21 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed std::vector> radiusSymbolRecord{}; - rc = sqlite3_exec(database, getRadiusType.c_str(), selectCallbackUsingColNameAsKey, &radiusSymbolRecord, - &errorMessage); + rc = sqlite3_exec(database, getRadiusType.c_str(), selectCallbackUsingColNameAsKey, &radiusSymbolRecord, &errorMessage); REQUIRE(rc == SQLITE_OK); - std::string radiusType{radiusSymbolRecord.at(0)["id"]}; + std::string radiusType{radiusSymbolRecord.at(0)["id"]}; REQUIRE(fieldsRecords.at(1)["symbol"] == circleRecords.at(0)["id"]); REQUIRE(fieldsRecords.at(1)["name"] == "radius"); REQUIRE(fieldsRecords.at(1)["byte_offset"] == std::to_string(offsetof(Circle, radius))); REQUIRE(fieldsRecords.at(1)["type"] == radiusType); REQUIRE(fieldsRecords.at(1)["little_endian"] == little_endian); + REQUIRE(fieldsRecords.at(1)["bit_size"] == "0"); + REQUIRE(fieldsRecords.at(1)["bit_offset"] == "0"); + REQUIRE(fieldsRecords.at(1)["short_description"] == ""); + REQUIRE(fieldsRecords.at(1)["long_description"] == ""); std::string getPointsType{"SELECT * FROM symbols where id="}; @@ -356,19 +427,21 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed std::vector> pointsSymbolRecord{}; - rc = sqlite3_exec(database, getPointsType.c_str(), selectCallbackUsingColNameAsKey, &pointsSymbolRecord, - &errorMessage); + rc = sqlite3_exec(database, getPointsType.c_str(), selectCallbackUsingColNameAsKey, &pointsSymbolRecord, &errorMessage); REQUIRE(rc == SQLITE_OK); - - std::string PointsType{pointsSymbolRecord.at(0)["id"]}; + std::string PointsType{pointsSymbolRecord.at(0)["id"]}; REQUIRE(fieldsRecords.at(2)["symbol"] == circleRecords.at(0)["id"]); REQUIRE(fieldsRecords.at(2)["name"] == "points"); REQUIRE(fieldsRecords.at(2)["byte_offset"] == std::to_string(offsetof(Circle, points))); REQUIRE(fieldsRecords.at(2)["type"] == PointsType); REQUIRE(fieldsRecords.at(2)["little_endian"] == little_endian); + REQUIRE(fieldsRecords.at(2)["bit_size"] == "0"); + REQUIRE(fieldsRecords.at(2)["bit_offset"] == "0"); + REQUIRE(fieldsRecords.at(2)["short_description"] == ""); + REQUIRE(fieldsRecords.at(2)["long_description"] == ""); /** *Check the correctness of the types @@ -379,9 +452,7 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed std::vector> diameterFieldSymbolRecord{}; - rc = sqlite3_exec(database, getDiameterFieldTypes.c_str(), selectCallbackUsingColNameAsKey, &diameterFieldSymbolRecord, - &errorMessage); - + rc = sqlite3_exec(database, getDiameterFieldTypes.c_str(), selectCallbackUsingColNameAsKey, &diameterFieldSymbolRecord, &errorMessage); REQUIRE(rc == SQLITE_OK); REQUIRE(diameterFieldSymbolRecord.size() == 1); @@ -390,16 +461,24 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed * 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: diameterFieldSymbolRecord) + for (auto record : diameterFieldSymbolRecord) { REQUIRE(record.find("id") != record.end()); REQUIRE(record.find("name") != record.end()); REQUIRE(record.find("byte_size") != record.end()); REQUIRE(record.find("elf") != record.end()); + REQUIRE(record.find("target_symbol") != record.end()); + REQUIRE(record.find("encoding") != record.end()); + REQUIRE(record.find("short_description") != record.end()); + REQUIRE(record.find("long_description") != record.end()); } REQUIRE(diameterFieldSymbolRecord.at(0)["name"] == "float"); REQUIRE(diameterFieldSymbolRecord.at(0)["byte_size"] == std::to_string(sizeof(float))); + REQUIRE(diameterFieldSymbolRecord.at(0)["target_symbol"] == "NULL"); + REQUIRE(encodingMap.at(diameterFieldSymbolRecord.at(0).at("encoding")) == "DW_ATE_float"); + REQUIRE(diameterFieldSymbolRecord.at(0)["short_description"] == ""); + REQUIRE(diameterFieldSymbolRecord.at(0)["long_description"] == ""); std::string getRadiusFieldTypes{"SELECT * FROM symbols WHERE id = "}; getRadiusFieldTypes += radiusType; @@ -407,8 +486,7 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed std::vector> radiusFieldTypesRecords{}; - rc = sqlite3_exec(database, getRadiusFieldTypes.c_str(), selectCallbackUsingColNameAsKey, &radiusFieldTypesRecords, - &errorMessage); + rc = sqlite3_exec(database, getRadiusFieldTypes.c_str(), selectCallbackUsingColNameAsKey, &radiusFieldTypesRecords, &errorMessage); REQUIRE(rc == SQLITE_OK); REQUIRE(radiusFieldTypesRecords.size() == 1); @@ -416,26 +494,32 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed * 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: radiusFieldTypesRecords) + for (auto record : radiusFieldTypesRecords) { REQUIRE(record.find("id") != record.end()); REQUIRE(record.find("name") != record.end()); REQUIRE(record.find("byte_size") != record.end()); REQUIRE(record.find("elf") != record.end()); + REQUIRE(record.find("target_symbol") != record.end()); + REQUIRE(record.find("encoding") != record.end()); + REQUIRE(record.find("short_description") != record.end()); + REQUIRE(record.find("long_description") != record.end()); } REQUIRE(radiusFieldTypesRecords.at(0)["name"] == "float"); REQUIRE(radiusFieldTypesRecords.at(0)["byte_size"] == std::to_string(sizeof(float))); + REQUIRE(radiusFieldTypesRecords.at(0)["target_symbol"] == "NULL"); + REQUIRE(encodingMap.at(radiusFieldTypesRecords.at(0).at("encoding")) == "DW_ATE_float"); + REQUIRE(radiusFieldTypesRecords.at(0)["short_description"] == ""); + REQUIRE(radiusFieldTypesRecords.at(0)["long_description"] == ""); std::string getPointsFieldTypes{"SELECT * FROM symbols WHERE id = "}; getPointsFieldTypes += PointsType; getPointsFieldTypes += ";"; - std::vector> pointsFieldTypesRecords{}; - rc = sqlite3_exec(database, getPointsFieldTypes.c_str(), selectCallbackUsingColNameAsKey, &pointsFieldTypesRecords, - &errorMessage); + rc = sqlite3_exec(database, getPointsFieldTypes.c_str(), selectCallbackUsingColNameAsKey, &pointsFieldTypesRecords, &errorMessage); REQUIRE(rc == SQLITE_OK); REQUIRE(pointsFieldTypesRecords.size() == 1); @@ -443,6 +527,10 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed REQUIRE(pointsFieldTypesRecords.at(0)["name"] == "int"); REQUIRE(pointsFieldTypesRecords.at(0)["byte_size"] == std::to_string(sizeof(int))); + REQUIRE(pointsFieldTypesRecords.at(0)["target_symbol"] == "NULL"); + REQUIRE(encodingMap.at(pointsFieldTypesRecords.at(0).at("encoding")) == "DW_ATE_signed"); + REQUIRE(pointsFieldTypesRecords.at(0)["short_description"] == ""); + REQUIRE(pointsFieldTypesRecords.at(0)["long_description"] == ""); REQUIRE(fieldsRecords.at(3)["name"] == "mode"); @@ -453,24 +541,22 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed std::vector> modeSymbolRecord{}; - rc = sqlite3_exec(database, getModeType.c_str(), selectCallbackUsingColNameAsKey, &modeSymbolRecord, - &errorMessage); + rc = sqlite3_exec(database, getModeType.c_str(), selectCallbackUsingColNameAsKey, &modeSymbolRecord, &errorMessage); REQUIRE(rc == SQLITE_OK); - std::string modeType{modeSymbolRecord.at(0)["id"]}; + std::string modeType{modeSymbolRecord.at(0)["id"]}; /* *Verify the mode field is an enumeration */ std::string getModeFieldTypes{"SELECT * FROM symbols WHERE id = "}; - getModeFieldTypes += modeType; + getModeFieldTypes += modeType; getRadiusFieldTypes += ";"; std::vector> modeFieldTypesRecords{}; - rc = sqlite3_exec(database, getModeFieldTypes.c_str(), selectCallbackUsingColNameAsKey, &modeFieldTypesRecords, - &errorMessage); + rc = sqlite3_exec(database, getModeFieldTypes.c_str(), selectCallbackUsingColNameAsKey, &modeFieldTypesRecords, &errorMessage); REQUIRE(rc == SQLITE_OK); REQUIRE(modeFieldTypesRecords.size() == 1); @@ -479,12 +565,16 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed * 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: modeFieldTypesRecords) + for (auto record : modeFieldTypesRecords) { REQUIRE(record.find("id") != record.end()); REQUIRE(record.find("name") != record.end()); REQUIRE(record.find("byte_size") != record.end()); REQUIRE(record.find("elf") != record.end()); + REQUIRE(record.find("target_symbol") != record.end()); + REQUIRE(record.find("encoding") != record.end()); + REQUIRE(record.find("short_description") != record.end()); + REQUIRE(record.find("long_description") != record.end()); } std::string getModeEnums{"SELECT * FROM enumerations WHERE symbol = "}; @@ -493,11 +583,10 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed std::vector> modeEnumsRecords{}; - rc = sqlite3_exec(database, getModeEnums.c_str(), selectCallbackUsingColNameAsKey, &modeEnumsRecords, - &errorMessage); + rc = sqlite3_exec(database, getModeEnums.c_str(), selectCallbackUsingColNameAsKey, &modeEnumsRecords, &errorMessage); REQUIRE(rc == SQLITE_OK); - REQUIRE(modeType == "31"); + // REQUIRE(modeType == "40"); REQUIRE(modeEnumsRecords.size() == 8); @@ -505,20 +594,19 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed * 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: modeEnumsRecords) + for (auto record : modeEnumsRecords) { REQUIRE(record.find("id") != record.end()); REQUIRE(record.find("symbol") != record.end()); REQUIRE(record.find("value") != record.end()); REQUIRE(record.find("name") != record.end()); + REQUIRE(record.find("short_description") != record.end()); + REQUIRE(record.find("long_description") != record.end()); } - //Enforce order of records by value + // Enforce order of records by value std::sort(modeEnumsRecords.begin(), modeEnumsRecords.end(), - [](std::map a, std::map b) - { - return std::stoi(a["value"]) < std::stoi(b["value"]); - }); + [](std::map a, std::map b) { return std::stoi(a["value"]) < std::stoi(b["value"]); }); REQUIRE(modeEnumsRecords[0]["name"] == "MODE_SLOT_NONE"); REQUIRE(modeEnumsRecords[0]["value"] == "-1"); @@ -537,65 +625,117 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed REQUIRE(modeEnumsRecords[7]["name"] == "MODE_SLOT_MAX"); REQUIRE(modeEnumsRecords[7]["value"] == "6"); + REQUIRE(fieldsRecords.at(4)["name"] == "_spare_end"); + /** + *Check the correctness of the fields + */ + + std::string getSpareEndType{"SELECT * FROM symbols where id="}; + + getSpareEndType += fieldsRecords.at(4)["type"]; + getSpareEndType += ";"; + + std::vector> spareEndSymbolRecords{}; + + rc = sqlite3_exec(database, getSpareEndType.c_str(), selectCallbackUsingColNameAsKey, &spareEndSymbolRecords, &errorMessage); + + REQUIRE(rc == SQLITE_OK); + + REQUIRE(spareEndSymbolRecords.size() == 1); + + std::string spareEndType{spareEndSymbolRecords.at(0).at("id")}; + + // TODO:Add support for unions first before adding these tests. + + // REQUIRE(fieldsRecords.at(4)["symbol"] == circleRecords.at(0)["id"]); + // REQUIRE(fieldsRecords.at(4)["name"] == "_spare_end"); + // REQUIRE(fieldsRecords.at(4)["byte_offset"] == std::to_string( sizeof(float) + sizeof(float) + (sizeof(int) * 128) + sizeof(ModeSlot_t) )); + // REQUIRE(fieldsRecords.at(4)["type"] == spareEndType); + // REQUIRE(fieldsRecords.at(4)["little_endian"] == little_endian); + // REQUIRE(fieldsRecords.at(4)["bit_size"] == "0"); + // REQUIRE(fieldsRecords.at(4)["bit_offset"] == "0"); + // REQUIRE(fieldsRecords.at(4)["short_description"] == ""); + // REQUIRE(fieldsRecords.at(4)["long_description"] == ""); + /** * *Clean up our database handle and objects in memory. */ - REQUIRE(remove("./test_db.sqlite")==0); + REQUIRE(remove("./test_db.sqlite") == 0); delete idc; } - -TEST_CASE("Test the correctness of the Circle struct after Juicer has processed it on two" - " different elf files." ,"[main_test#3]") +TEST_CASE( + "Test the correctness of the Circle struct after Juicer has processed it on two" + " different elf files.", + "[main_test#3]") { - /** - * This assumes that the test_file was compiled on - * gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 - * little-endian machine. - */ + /** + * 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; - char* errorMessage = nullptr; - std::string little_endian = is_little_endian()? "1": "0"; + int rc; + char* errorMessage = nullptr; + std::string little_endian = is_little_endian() ? "1" : "0"; logger.logWarning("This is just a test."); std::string inputFile{TEST_FILE_1}; idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); - REQUIRE(idc!=nullptr); + 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); inputFile = TEST_FILE_2; - rc = juicer.parse(inputFile); + rc = juicer.parse(inputFile); + REQUIRE((juicer.getDwarfVersion() == 4 || juicer.getDwarfVersion() == 5)); REQUIRE(rc == JUICER_OK); std::string getCircleStructQuery{"SELECT * FROM symbols WHERE name = \"Circle\"; "}; - sqlite3 *database; + sqlite3* database; rc = sqlite3_open("./test_db.sqlite", &database); REQUIRE(rc == SQLITE_OK); - columnNameToRowMap circleDataMap{}; - circleDataMap.colName = "name"; + std::string getAllEncodings{"SELECT * FROM encodings"}; - std::vector> circleRecords{}; + std::vector> encodingsRecords{}; + + rc = sqlite3_exec(database, getAllEncodings.c_str(), selectCallbackUsingColNameAsKey, &encodingsRecords, &errorMessage); + + REQUIRE(rc == SQLITE_OK); + + REQUIRE(encodingsRecords.size() == 18); + + /** + * @brief encodingMap A map of row_id -> encoding. + * i.e {"1":"DW_ATE_address", "2":"DW_ATE_boolean", etc}. Useful for avoiding having to look up the encoding by foreign of a symbol + * every time. + */ + std::map encodingMap{}; + + for (auto encodingRecord : encodingsRecords) + { + encodingMap[encodingRecord["id"]] = encodingRecord["encoding"]; + } + std::vector> circleRecords{}; - rc = sqlite3_exec(database, getCircleStructQuery.c_str(), selectCallbackUsingColNameAsKey, &circleRecords, - &errorMessage); + rc = sqlite3_exec(database, getCircleStructQuery.c_str(), selectCallbackUsingColNameAsKey, &circleRecords, &errorMessage); REQUIRE(rc == SQLITE_OK); REQUIRE(circleRecords.size() == 1); @@ -606,11 +746,16 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed REQUIRE(circleRecords.at(0)["name"] == "Circle"); REQUIRE(circleRecords.at(0)["byte_size"] == std::to_string(sizeof(Circle))); + REQUIRE(circleRecords.at(0)["target_symbol"] == "NULL"); + REQUIRE(circleRecords.at(0).at("encoding") == "NULL"); + REQUIRE(circleRecords.at(0)["short_description"] == ""); + REQUIRE(circleRecords.at(0)["long_description"] == ""); + /** *Check the fields of the Circle struct. - */ + */ - std::string circle_id = circleRecords.at(0)["id"]; + std::string circle_id = circleRecords.at(0)["id"]; std::string ciircle_artifact_id = circleRecords.at(0)["artifact"]; @@ -621,16 +766,14 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed getCircleArtifact += ciircle_artifact_id; getCircleArtifact += ";"; - std::vector> circleArtifactRecords{}; - rc = sqlite3_exec(database, getCircleArtifact.c_str(), selectCallbackUsingColNameAsKey, &circleArtifactRecords, - &errorMessage); + rc = sqlite3_exec(database, getCircleArtifact.c_str(), selectCallbackUsingColNameAsKey, &circleArtifactRecords, &errorMessage); REQUIRE(circleArtifactRecords.size() == 1); std::string path{}; - char resolvedPath[PATH_MAX]; + char resolvedPath[PATH_MAX]; realpath("../unit-test/test_file1.h", resolvedPath); @@ -639,39 +782,34 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed REQUIRE(circleArtifactRecords.at(0)["path"] == path); - std::string expectedMD5Str = getmd5sumFromSystem(resolvedPath); + std::string expectedMD5Str = getmd5sumFromSystem(resolvedPath); REQUIRE(expectedMD5Str == circleArtifactRecords.at(0)["md5"]); - REQUIRE(!circleArtifactRecords.at(0)["elf"].empty()); - std::string getCircleElf{"SELECT * FROM elfs WHERE id = "}; getCircleElf += circleArtifactRecords.at(0)["elf"]; getCircleElf += ";"; - std::vector> circleElftRecords{}; - rc = sqlite3_exec(database, getCircleElf.c_str(), selectCallbackUsingColNameAsKey, &circleElftRecords, - &errorMessage); + rc = sqlite3_exec(database, getCircleElf.c_str(), selectCallbackUsingColNameAsKey, &circleElftRecords, &errorMessage); REQUIRE(circleElftRecords.size() == 1); uint32_t numberOfColumns = 0; - for(auto pair: circleElftRecords.at(0)) + for (auto pair : circleElftRecords.at(0)) { - numberOfColumns++; + numberOfColumns++; } REQUIRE(numberOfColumns == 5); - memset(&resolvedPath, '\0', PATH_MAX); - realpath("./ut_obj/test_file1.o", resolvedPath); + realpath(TEST_FILE_1, resolvedPath); path.clear(); path.insert(0, resolvedPath); @@ -680,29 +818,24 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed expectedMD5Str.clear(); - std::string expectedMD5Str2 = getmd5sumFromSystem(resolvedPath); - REQUIRE(expectedMD5Str2 == circleElftRecords.at(0)["md5"]); + std::string expectedMD5Str2 = getmd5sumFromSystem(resolvedPath); + REQUIRE(expectedMD5Str2 == circleElftRecords.at(0)["md5"]); std::string getCircleFields{"SELECT * FROM fields WHERE symbol = "}; getCircleFields += circle_id; getCircleFields += ";"; - std::vector> circleFieldsRecords{}; - rc = sqlite3_exec(database, getCircleFields.c_str(), selectCallbackUsingColNameAsKey, &circleFieldsRecords, - &errorMessage); + rc = sqlite3_exec(database, getCircleFields.c_str(), selectCallbackUsingColNameAsKey, &circleFieldsRecords, &errorMessage); REQUIRE(rc == SQLITE_OK); REQUIRE(circleFieldsRecords.size() == 5); - //Enforce order of records by offset - std::sort(circleFieldsRecords.begin(), circleFieldsRecords.end(), - [](std::map a, std::map b) - { - return std::stoi(a["byte_offset"]) < std::stoi(b["byte_offset"]); - }); + // Enforce order of records by offset + std::sort(circleFieldsRecords.begin(), circleFieldsRecords.end(), [](std::map a, std::map b) + { return std::stoi(a["byte_offset"]) < std::stoi(b["byte_offset"]); }); /** *Check the correctness of the fields @@ -715,13 +848,12 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed std::vector> diameterTypeRecords{}; - rc = sqlite3_exec(database, getDiameterType.c_str(), selectCallbackUsingColNameAsKey, &diameterTypeRecords, - &errorMessage); + rc = sqlite3_exec(database, getDiameterType.c_str(), selectCallbackUsingColNameAsKey, &diameterTypeRecords, &errorMessage); REQUIRE(rc == SQLITE_OK); REQUIRE(diameterTypeRecords.size() == 1); - std::string diameterType{diameterTypeRecords.at(0)["id"]}; + std::string diameterType{diameterTypeRecords.at(0)["id"]}; REQUIRE(circleFieldsRecords.at(0)["symbol"] == circleRecords.at(0)["id"]); REQUIRE(circleFieldsRecords.at(0)["name"] == "diameter"); @@ -729,6 +861,9 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed REQUIRE(circleFieldsRecords.at(0)["type"] == diameterType); REQUIRE(circleFieldsRecords.at(0)["little_endian"] == little_endian); + REQUIRE(circleFieldsRecords.at(0)["short_description"] == ""); + REQUIRE(circleFieldsRecords.at(0)["long_description"] == ""); + std::string getRadiusType{"SELECT * FROM symbols where id="}; getRadiusType += circleFieldsRecords.at(1)["type"]; @@ -736,14 +871,13 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed std::vector> radiusTypeRecords{}; - rc = sqlite3_exec(database, getRadiusType.c_str(), selectCallbackUsingColNameAsKey, &radiusTypeRecords, - &errorMessage); + rc = sqlite3_exec(database, getRadiusType.c_str(), selectCallbackUsingColNameAsKey, &radiusTypeRecords, &errorMessage); REQUIRE(rc == SQLITE_OK); REQUIRE(radiusTypeRecords.size() == 1); REQUIRE(radiusTypeRecords.at(0).find("id") != radiusTypeRecords.at(0).end()); - std::string radiusType{radiusTypeRecords.at(0)["id"]}; + std::string radiusType{radiusTypeRecords.at(0)["id"]}; REQUIRE(circleFieldsRecords.at(1)["symbol"] == circleRecords.at(0)["id"]); REQUIRE(circleFieldsRecords.at(1)["name"] == "radius"); @@ -751,6 +885,9 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed REQUIRE(circleFieldsRecords.at(1)["type"] == radiusType); REQUIRE(circleFieldsRecords.at(1)["little_endian"] == little_endian); + REQUIRE(circleFieldsRecords.at(1)["short_description"] == ""); + REQUIRE(circleFieldsRecords.at(1)["long_description"] == ""); + /** *Check the correctness of the types */ @@ -760,8 +897,7 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed std::vector> diameterFieldTypeRecords{}; - rc = sqlite3_exec(database, getDiameterFieldTypes.c_str(), selectCallbackUsingColNameAsKey, &diameterFieldTypeRecords, - &errorMessage); + rc = sqlite3_exec(database, getDiameterFieldTypes.c_str(), selectCallbackUsingColNameAsKey, &diameterFieldTypeRecords, &errorMessage); REQUIRE(rc == SQLITE_OK); REQUIRE(diameterFieldTypeRecords.size() == 1); @@ -769,40 +905,47 @@ TEST_CASE("Test the correctness of the Circle struct after Juicer has processed REQUIRE(diameterFieldTypeRecords.at(0)["name"] == "float"); REQUIRE(diameterFieldTypeRecords.at(0)["byte_size"] == std::to_string(sizeof(float))); + REQUIRE(diameterFieldTypeRecords.at(0)["target_symbol"] == "NULL"); + REQUIRE(encodingMap.at(diameterFieldTypeRecords.at(0).at("encoding")) == "DW_ATE_float"); + REQUIRE(diameterFieldTypeRecords.at(0)["short_description"] == ""); + REQUIRE(diameterFieldTypeRecords.at(0)["long_description"] == ""); + /** * *Clean up our database handle and objects in memory. */ - REQUIRE(remove("./test_db.sqlite")==0); + REQUIRE(remove("./test_db.sqlite") == 0); ((SQLiteDB*)(idc))->close(); delete idc; } -TEST_CASE("Test the correctness of the Square struct after Juicer has processed it." ,"[main_test#4]") +TEST_CASE("Test the correctness of the Square struct after Juicer has processed it.", "[main_test#4]") { - /** - * This assumes that the test_file was compiled on - * gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 - * little-endian machine. - */ + /** + * 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"; + 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_1}; idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); - REQUIRE(idc!=nullptr); + 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); std::string getSquareStructQuery{"SELECT * FROM symbols WHERE name = \"Square\"; "}; @@ -812,28 +955,49 @@ TEST_CASE("Test the correctness of the Square struct after Juicer has processed */ ((SQLiteDB*)(idc))->close(); - sqlite3 *database; + sqlite3* database; rc = sqlite3_open("./test_db.sqlite", &database); REQUIRE(rc == SQLITE_OK); + std::string getAllEncodings{"SELECT * FROM encodings"}; + + std::vector> encodingsRecords{}; + + rc = sqlite3_exec(database, getAllEncodings.c_str(), selectCallbackUsingColNameAsKey, &encodingsRecords, &errorMessage); + + REQUIRE(rc == SQLITE_OK); + + REQUIRE(encodingsRecords.size() == 18); + + /** + * @brief encodingMap A map of row_id -> encoding. + * i.e {"1":"DW_ATE_address", "2":"DW_ATE_boolean", etc}. Useful for avoiding having to look up the encoding by foreign of a symbol + * every time. + */ + std::map encodingMap{}; + + for (auto encodingRecord : encodingsRecords) + { + encodingMap[encodingRecord["id"]] = encodingRecord["encoding"]; + } + std::vector> squareRecords{}; - rc = sqlite3_exec(database, getSquareStructQuery.c_str(), selectCallbackUsingColNameAsKey, &squareRecords, - &errorMessage); + rc = sqlite3_exec(database, getSquareStructQuery.c_str(), selectCallbackUsingColNameAsKey, &squareRecords, &errorMessage); REQUIRE(rc == SQLITE_OK); - REQUIRE(squareRecords.size() == 1); + REQUIRE(squareRecords.size() == 1); uint32_t numberOfColumns = 0; - for(auto pair: squareRecords.at(0)) + for (auto pair : squareRecords.at(0)) { - numberOfColumns++; + numberOfColumns++; } - REQUIRE(numberOfColumns == 7); + REQUIRE(numberOfColumns == 9); /** * Check the correctness of Square struct. @@ -842,8 +1006,12 @@ TEST_CASE("Test the correctness of the Square struct after Juicer has processed REQUIRE(squareRecords.at(0)["name"] == "Square"); REQUIRE(squareRecords.at(0)["byte_size"] == std::to_string(sizeof(Square))); + REQUIRE(squareRecords.at(0)["target_symbol"] == "NULL"); + REQUIRE(squareRecords.at(0).at("encoding") == "NULL"); + REQUIRE(squareRecords.at(0)["short_description"] == ""); + REQUIRE(squareRecords.at(0)["long_description"] == ""); - std::string square_id = squareRecords.at(0)["id"]; + std::string square_id = squareRecords.at(0)["id"]; std::string square_artifact_id = squareRecords.at(0)["artifact"]; @@ -856,13 +1024,12 @@ TEST_CASE("Test the correctness of the Square struct after Juicer has processed std::vector> squareArtifactRecords{}; - rc = sqlite3_exec(database, getSquareArtifact.c_str(), selectCallbackUsingColNameAsKey, &squareArtifactRecords, - &errorMessage); + rc = sqlite3_exec(database, getSquareArtifact.c_str(), selectCallbackUsingColNameAsKey, &squareArtifactRecords, &errorMessage); REQUIRE(squareArtifactRecords.size() == 1); std::string path{}; - char resolvedPath[PATH_MAX]; + char resolvedPath[PATH_MAX]; realpath("../unit-test/test_file1.h", resolvedPath); @@ -871,7 +1038,7 @@ TEST_CASE("Test the correctness of the Square struct after Juicer has processed REQUIRE(squareArtifactRecords.at(0)["path"] == path); - std::string expectedMD5Str = getmd5sumFromSystem(resolvedPath); + std::string expectedMD5Str = getmd5sumFromSystem(resolvedPath); REQUIRE(expectedMD5Str == squareArtifactRecords.at(0)["md5"]); std::string getSquareFields{"SELECT * FROM fields WHERE symbol = "}; @@ -881,18 +1048,14 @@ TEST_CASE("Test the correctness of the Square struct after Juicer has processed std::vector> squareFieldsRecords{}; - rc = sqlite3_exec(database, getSquareFields.c_str(), selectCallbackUsingColNameAsKey, &squareFieldsRecords, - &errorMessage); + rc = sqlite3_exec(database, getSquareFields.c_str(), selectCallbackUsingColNameAsKey, &squareFieldsRecords, &errorMessage); REQUIRE(rc == SQLITE_OK); - REQUIRE(squareFieldsRecords.size() == 9); + REQUIRE(squareFieldsRecords.size() == 11); - //Enforce order of records by offset - std::sort(squareFieldsRecords.begin(), squareFieldsRecords.end(), - [](std::map a, std::map b) - { - return std::stoi(a["byte_offset"]) < std::stoi(b["byte_offset"]); - }); + // Enforce order of records by offset + std::sort(squareFieldsRecords.begin(), squareFieldsRecords.end(), [](std::map a, std::map b) + { return std::stoi(a["byte_offset"]) < std::stoi(b["byte_offset"]); }); std::string getWidthType{"SELECT * FROM symbols where id="}; getWidthType += squareFieldsRecords.at(0)["type"]; @@ -900,12 +1063,11 @@ TEST_CASE("Test the correctness of the Square struct after Juicer has processed std::vector> widthTypeRecords{}; - rc = sqlite3_exec(database, getWidthType.c_str(), selectCallbackUsingColNameAsKey, &widthTypeRecords, - &errorMessage); + rc = sqlite3_exec(database, getWidthType.c_str(), selectCallbackUsingColNameAsKey, &widthTypeRecords, &errorMessage); REQUIRE(rc == SQLITE_OK); REQUIRE(widthTypeRecords.size() == 1); - std::string widthType{widthTypeRecords.at(0)["id"]}; + std::string widthType{widthTypeRecords.at(0)["id"]}; REQUIRE(squareFieldsRecords.at(0)["symbol"] == squareRecords.at(0)["id"]); REQUIRE(squareFieldsRecords.at(0)["name"] == "width"); @@ -913,177 +1075,202 @@ TEST_CASE("Test the correctness of the Square struct after Juicer has processed REQUIRE(squareFieldsRecords.at(0)["type"] == widthType); REQUIRE(squareFieldsRecords.at(0)["little_endian"] == little_endian); - std::string getStuffType{"SELECT * FROM symbols where id="}; getStuffType += squareFieldsRecords.at(1)["type"]; getStuffType += ";"; std::vector> stuffTypeRecords{}; - rc = sqlite3_exec(database, getStuffType.c_str(), selectCallbackUsingColNameAsKey, &stuffTypeRecords, - &errorMessage); + rc = sqlite3_exec(database, getStuffType.c_str(), selectCallbackUsingColNameAsKey, &stuffTypeRecords, &errorMessage); REQUIRE(rc == SQLITE_OK); REQUIRE(stuffTypeRecords.size() == 1); - std::string stuffType{stuffTypeRecords.at(0)["id"]}; + REQUIRE(stuffTypeRecords.at(0)["name"] == "uint16_t"); + REQUIRE(stuffTypeRecords.at(0)["byte_size"] == std::to_string(sizeof(uint16_t))); + + REQUIRE(encodingMap.at(followTargetSymbol(database, stuffTypeRecords.at(0)["target_symbol"]).at("encoding")) == "DW_ATE_unsigned"); + REQUIRE(stuffTypeRecords.at(0)["short_description"] == ""); + REQUIRE(stuffTypeRecords.at(0)["long_description"] == ""); + + std::string stuffType{stuffTypeRecords.at(0)["id"]}; REQUIRE(squareFieldsRecords.at(1)["name"] == "stuff"); REQUIRE(squareFieldsRecords.at(1)["byte_offset"] == std::to_string(offsetof(Square, stuff))); - REQUIRE(squareFieldsRecords.at(1)["type"] == stuffType); - REQUIRE(squareFieldsRecords.at(1)["little_endian"] == little_endian); + REQUIRE(squareFieldsRecords.at(1)["type"] == stuffType); + REQUIRE(squareFieldsRecords.at(1)["little_endian"] == little_endian); + + std::string getPadding1Type{"SELECT * FROM symbols where id="}; + getPadding1Type += squareFieldsRecords.at(2)["type"]; + getPadding1Type += ";"; + + std::vector> padding1TypeRecords{}; + + rc = sqlite3_exec(database, getPadding1Type.c_str(), selectCallbackUsingColNameAsKey, &padding1TypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(padding1TypeRecords.size() == 1); + + REQUIRE(padding1TypeRecords.at(0)["name"] == "uint16_t"); + REQUIRE(padding1TypeRecords.at(0)["byte_size"] == std::to_string(sizeof(uint16_t))); + + REQUIRE(encodingMap.at(followTargetSymbol(database, padding1TypeRecords.at(0)["target_symbol"]).at("encoding")) == "DW_ATE_unsigned"); + REQUIRE(padding1TypeRecords.at(0)["short_description"] == ""); + REQUIRE(padding1TypeRecords.at(0)["long_description"] == ""); + + std::string padding1Type{padding1TypeRecords.at(0)["id"]}; + REQUIRE(squareFieldsRecords.at(2)["name"] == "padding1"); + REQUIRE(squareFieldsRecords.at(2)["byte_offset"] == std::to_string(offsetof(Square, padding1))); + REQUIRE(squareFieldsRecords.at(2)["type"] == padding1Type); + REQUIRE(squareFieldsRecords.at(2)["little_endian"] == little_endian); - std::string getPadding1Type{"SELECT * FROM symbols where id="}; - getPadding1Type += squareFieldsRecords.at(2)["type"]; - getPadding1Type += ";"; + std::string getLengthType{"SELECT * FROM symbols where id="}; + getLengthType += squareFieldsRecords.at(3)["type"]; + getLengthType += ";"; - std::vector> padding1TypeRecords{}; + std::vector> lengthTypeRecords{}; - rc = sqlite3_exec(database, getPadding1Type.c_str(), selectCallbackUsingColNameAsKey, &padding1TypeRecords, - &errorMessage); - REQUIRE(rc == SQLITE_OK); - REQUIRE(padding1TypeRecords.size() == 1); + rc = sqlite3_exec(database, getLengthType.c_str(), selectCallbackUsingColNameAsKey, &lengthTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(lengthTypeRecords.size() == 1); + + REQUIRE(lengthTypeRecords.at(0)["name"] == "int32_t"); + REQUIRE(lengthTypeRecords.at(0)["byte_size"] == std::to_string(sizeof(int32_t))); - std::string padding1Type{padding1TypeRecords.at(0)["id"]}; + REQUIRE(encodingMap.at(followTargetSymbol(database, lengthTypeRecords.at(0)["target_symbol"]).at("encoding")) == "DW_ATE_signed"); + REQUIRE(lengthTypeRecords.at(0)["short_description"] == ""); + REQUIRE(lengthTypeRecords.at(0)["long_description"] == ""); - REQUIRE(squareFieldsRecords.at(2)["name"] == "padding1"); - REQUIRE(squareFieldsRecords.at(2)["byte_offset"] == std::to_string(offsetof(Square, padding1))); - REQUIRE(squareFieldsRecords.at(2)["type"] == padding1Type); - REQUIRE(squareFieldsRecords.at(2)["little_endian"] == little_endian); + std::string lengthType{lengthTypeRecords.at(0)["id"]}; - std::string getLengthType{"SELECT * FROM symbols where id="}; - getLengthType += squareFieldsRecords.at(3)["type"]; - getLengthType += ";"; + REQUIRE(squareFieldsRecords.at(3)["name"] == "length"); + REQUIRE(squareFieldsRecords.at(3)["byte_offset"] == std::to_string(offsetof(Square, length))); + REQUIRE(squareFieldsRecords.at(3)["type"] == lengthType); + REQUIRE(squareFieldsRecords.at(3)["little_endian"] == little_endian); - std::vector> lengthTypeRecords{}; + std::string getMoreStuffType{"SELECT * FROM symbols where id="}; + getMoreStuffType += squareFieldsRecords.at(4)["type"]; + getMoreStuffType += ";"; - rc = sqlite3_exec(database, getLengthType.c_str(), selectCallbackUsingColNameAsKey, &lengthTypeRecords, - &errorMessage); - REQUIRE(rc == SQLITE_OK); - REQUIRE(lengthTypeRecords.size() == 1); + std::vector> moreStuffTypeRecords{}; - std::string lengthType{lengthTypeRecords.at(0)["id"]}; + rc = sqlite3_exec(database, getMoreStuffType.c_str(), selectCallbackUsingColNameAsKey, &moreStuffTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(moreStuffTypeRecords.size() == 1); - REQUIRE(squareFieldsRecords.at(3)["name"] == "length"); - REQUIRE(squareFieldsRecords.at(3)["byte_offset"] == std::to_string(offsetof(Square, length))); - REQUIRE(squareFieldsRecords.at(3)["type"] == lengthType); - REQUIRE(squareFieldsRecords.at(3)["little_endian"] == little_endian); + REQUIRE(moreStuffTypeRecords.at(0)["name"] == "uint16_t"); + REQUIRE(moreStuffTypeRecords.at(0)["byte_size"] == std::to_string(sizeof(uint16_t))); - std::string getMoreStuffType{"SELECT * FROM symbols where id="}; - getMoreStuffType += squareFieldsRecords.at(4)["type"]; - getMoreStuffType += ";"; + REQUIRE(encodingMap.at(followTargetSymbol(database, moreStuffTypeRecords.at(0)["target_symbol"]).at("encoding")) == "DW_ATE_unsigned"); + REQUIRE(moreStuffTypeRecords.at(0)["short_description"] == ""); + REQUIRE(moreStuffTypeRecords.at(0)["long_description"] == ""); - std::vector> moreStuffTypeRecords{}; + std::string moreStuffType{moreStuffTypeRecords.at(0)["id"]}; - rc = sqlite3_exec(database, getMoreStuffType.c_str(), selectCallbackUsingColNameAsKey, &moreStuffTypeRecords, - &errorMessage); - REQUIRE(rc == SQLITE_OK); - REQUIRE(moreStuffTypeRecords.size() == 1); + REQUIRE(squareFieldsRecords.at(4)["name"] == "more_stuff"); + REQUIRE(squareFieldsRecords.at(4)["byte_offset"] == std::to_string(offsetof(Square, more_stuff))); + REQUIRE(squareFieldsRecords.at(4)["type"] == moreStuffType); + REQUIRE(squareFieldsRecords.at(4)["little_endian"] == little_endian); - std::string moreStuffType{moreStuffTypeRecords.at(0)["id"]}; + std::string getPadding2Type{"SELECT * FROM symbols where id="}; + getPadding2Type += squareFieldsRecords.at(5)["type"]; + getPadding2Type += ";"; - REQUIRE(squareFieldsRecords.at(4)["name"] == "more_stuff"); - REQUIRE(squareFieldsRecords.at(4)["byte_offset"] == std::to_string(offsetof(Square, more_stuff))); - REQUIRE(squareFieldsRecords.at(4)["type"] == moreStuffType); - REQUIRE(squareFieldsRecords.at(4)["little_endian"] == little_endian); + std::vector> padding2TypeRecords{}; + rc = sqlite3_exec(database, getPadding2Type.c_str(), selectCallbackUsingColNameAsKey, &padding2TypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(padding2TypeRecords.size() == 1); - std::string getPadding2Type{"SELECT * FROM symbols where id="}; - getPadding2Type += squareFieldsRecords.at(5)["type"]; - getPadding2Type += ";"; + REQUIRE(padding2TypeRecords.at(0)["name"] == "uint16_t"); + REQUIRE(padding2TypeRecords.at(0)["byte_size"] == std::to_string(sizeof(uint16_t))); - std::vector> padding2TypeRecords{}; + REQUIRE(encodingMap.at(followTargetSymbol(database, padding2TypeRecords.at(0)["target_symbol"]).at("encoding")) == "DW_ATE_unsigned"); + REQUIRE(padding2TypeRecords.at(0)["short_description"] == ""); + REQUIRE(padding2TypeRecords.at(0)["long_description"] == ""); - rc = sqlite3_exec(database, getPadding2Type.c_str(), selectCallbackUsingColNameAsKey, &padding2TypeRecords, - &errorMessage); - REQUIRE(rc == SQLITE_OK); - REQUIRE(padding2TypeRecords.size() == 1); + std::string padding2Type{padding2TypeRecords.at(0)["id"]}; - std::string padding2Type{padding2TypeRecords.at(0)["id"]}; + REQUIRE(squareFieldsRecords.at(5)["name"] == "padding2"); + REQUIRE(squareFieldsRecords.at(5)["byte_offset"] == std::to_string(offsetof(Square, padding2))); + REQUIRE(squareFieldsRecords.at(5)["type"] == padding2Type); + REQUIRE(squareFieldsRecords.at(5)["little_endian"] == little_endian); - REQUIRE(squareFieldsRecords.at(5)["name"] == "padding2"); - REQUIRE(squareFieldsRecords.at(5)["byte_offset"] == std::to_string(offsetof(Square, padding2))); - REQUIRE(squareFieldsRecords.at(5)["type"] == padding2Type); - REQUIRE(squareFieldsRecords.at(5)["little_endian"] == little_endian); + std::string getFloatingStuffType{"SELECT * FROM symbols where id="}; + getFloatingStuffType += squareFieldsRecords.at(6)["type"]; + getFloatingStuffType += ";"; - std::string getFloatingStuffType{"SELECT * FROM symbols where id="}; - getFloatingStuffType += squareFieldsRecords.at(6)["type"]; - getFloatingStuffType += ";"; + std::vector> floatingStuffTypeRecords{}; - std::vector> floatingStuffTypeRecords{}; + rc = sqlite3_exec(database, getFloatingStuffType.c_str(), selectCallbackUsingColNameAsKey, &floatingStuffTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(floatingStuffTypeRecords.size() == 1); - rc = sqlite3_exec(database, getFloatingStuffType.c_str(), selectCallbackUsingColNameAsKey, &floatingStuffTypeRecords, - &errorMessage); - REQUIRE(rc == SQLITE_OK); - REQUIRE(floatingStuffTypeRecords.size() == 1); + REQUIRE(floatingStuffTypeRecords.at(0)["name"] == "float"); + REQUIRE(floatingStuffTypeRecords.at(0)["byte_size"] == std::to_string(sizeof(float))); + REQUIRE(floatingStuffTypeRecords.at(0)["target_symbol"] == "NULL"); - std::string floatingStuffType{floatingStuffTypeRecords.at(0)["id"]}; + REQUIRE(encodingMap.at(floatingStuffTypeRecords.at(0)["encoding"]) == "DW_ATE_float"); + REQUIRE(floatingStuffTypeRecords.at(0)["short_description"] == ""); + REQUIRE(floatingStuffTypeRecords.at(0)["long_description"] == ""); - REQUIRE(squareFieldsRecords.at(6)["name"] == "floating_stuff"); - REQUIRE(squareFieldsRecords.at(6)["byte_offset"] == std::to_string(offsetof(Square, floating_stuff))); - REQUIRE(squareFieldsRecords.at(6)["type"] == floatingStuffType); - REQUIRE(squareFieldsRecords.at(6)["little_endian"] == little_endian); + std::string floatingStuffType{floatingStuffTypeRecords.at(0)["id"]}; - //Test matrix3D[2][4][4] - std::string getMatrix3DDimensionLists{"SELECT * FROM dimension_lists WHERE field_id="}; - getMatrix3DDimensionLists += squareFieldsRecords.at(7)["id"]; - getMatrix3DDimensionLists += ";"; + REQUIRE(squareFieldsRecords.at(6)["name"] == "floating_stuff"); + REQUIRE(squareFieldsRecords.at(6)["byte_offset"] == std::to_string(offsetof(Square, floating_stuff))); + REQUIRE(squareFieldsRecords.at(6)["type"] == floatingStuffType); + REQUIRE(squareFieldsRecords.at(6)["little_endian"] == little_endian); - std::vector> matrix3DDimensionListsRecords{}; + // Test matrix3D[2][4][4] + std::string getMatrix3DDimensionLists{"SELECT * FROM dimension_lists WHERE field_id="}; + getMatrix3DDimensionLists += squareFieldsRecords.at(7)["id"]; + getMatrix3DDimensionLists += ";"; - rc = sqlite3_exec(database, getMatrix3DDimensionLists.c_str(), selectCallbackUsingColNameAsKey, &matrix3DDimensionListsRecords, - &errorMessage); - REQUIRE(rc == SQLITE_OK); - REQUIRE(matrix3DDimensionListsRecords.size() == 3); + std::vector> matrix3DDimensionListsRecords{}; - //Enforce order of records by dim_order - std::sort(matrix3DDimensionListsRecords.begin(), matrix3DDimensionListsRecords.end(), - [](std::map a, std::map b) - { - return std::stoi(a["dim_order"]) < std::stoi(b["dim_order"]); - }); + rc = sqlite3_exec(database, getMatrix3DDimensionLists.c_str(), selectCallbackUsingColNameAsKey, &matrix3DDimensionListsRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(matrix3DDimensionListsRecords.size() == 3); - REQUIRE(matrix3DDimensionListsRecords.at(0)["field_id"] == squareFieldsRecords.at(7)["id"]); - REQUIRE(matrix3DDimensionListsRecords.at(0)["dim_order"] == "0"); - REQUIRE(matrix3DDimensionListsRecords.at(0)["upper_bound"] == "1"); + // Enforce order of records by dim_order + std::sort(matrix3DDimensionListsRecords.begin(), matrix3DDimensionListsRecords.end(), + [](std::map a, std::map b) { return std::stoi(a["dim_order"]) < std::stoi(b["dim_order"]); }); - REQUIRE(matrix3DDimensionListsRecords.at(1)["field_id"] == squareFieldsRecords.at(7)["id"]); - REQUIRE(matrix3DDimensionListsRecords.at(1)["dim_order"] == "1"); - REQUIRE(matrix3DDimensionListsRecords.at(1)["upper_bound"] == "3"); + REQUIRE(matrix3DDimensionListsRecords.at(0)["field_id"] == squareFieldsRecords.at(7)["id"]); + REQUIRE(matrix3DDimensionListsRecords.at(0)["dim_order"] == "0"); + REQUIRE(matrix3DDimensionListsRecords.at(0)["upper_bound"] == "1"); - REQUIRE(matrix3DDimensionListsRecords.at(2)["field_id"] == squareFieldsRecords.at(7)["id"]); - REQUIRE(matrix3DDimensionListsRecords.at(2)["dim_order"] == "2"); - REQUIRE(matrix3DDimensionListsRecords.at(2)["upper_bound"] == "3"); + REQUIRE(matrix3DDimensionListsRecords.at(1)["field_id"] == squareFieldsRecords.at(7)["id"]); + REQUIRE(matrix3DDimensionListsRecords.at(1)["dim_order"] == "1"); + REQUIRE(matrix3DDimensionListsRecords.at(1)["upper_bound"] == "3"); + REQUIRE(matrix3DDimensionListsRecords.at(2)["field_id"] == squareFieldsRecords.at(7)["id"]); + REQUIRE(matrix3DDimensionListsRecords.at(2)["dim_order"] == "2"); + REQUIRE(matrix3DDimensionListsRecords.at(2)["upper_bound"] == "3"); - //Test matrix3D[2][4][4] - std::string getMatrix1DDimensionLists{"SELECT * FROM dimension_lists WHERE field_id="}; - getMatrix1DDimensionLists += squareFieldsRecords.at(8)["id"]; - getMatrix1DDimensionLists += ";"; + // Test matrix3D[2][4][4] + std::string getMatrix1DDimensionLists{"SELECT * FROM dimension_lists WHERE field_id="}; + getMatrix1DDimensionLists += squareFieldsRecords.at(8)["id"]; + getMatrix1DDimensionLists += ";"; - std::vector> matrix1DDimensionListsRecords{}; + std::vector> matrix1DDimensionListsRecords{}; - rc = sqlite3_exec(database, getMatrix1DDimensionLists.c_str(), selectCallbackUsingColNameAsKey, &matrix1DDimensionListsRecords, - &errorMessage); - REQUIRE(rc == SQLITE_OK); - REQUIRE(matrix1DDimensionListsRecords.size() == 1); + rc = sqlite3_exec(database, getMatrix1DDimensionLists.c_str(), selectCallbackUsingColNameAsKey, &matrix1DDimensionListsRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(matrix1DDimensionListsRecords.size() == 1); - //Enforce order of records by dim_order - std::sort(matrix1DDimensionListsRecords.begin(), matrix1DDimensionListsRecords.end(), - [](std::map a, std::map b) - { - return std::stoi(a["dim_order"]) < std::stoi(b["dim_order"]); - }); + // Enforce order of records by dim_order + std::sort(matrix1DDimensionListsRecords.begin(), matrix1DDimensionListsRecords.end(), + [](std::map a, std::map b) { return std::stoi(a["dim_order"]) < std::stoi(b["dim_order"]); }); - REQUIRE(matrix1DDimensionListsRecords.at(0)["field_id"] == squareFieldsRecords.at(8)["id"]); - REQUIRE(matrix1DDimensionListsRecords.at(0)["dim_order"] == "0"); - REQUIRE(matrix1DDimensionListsRecords.at(0)["upper_bound"] == "1"); + REQUIRE(matrix1DDimensionListsRecords.at(0)["field_id"] == squareFieldsRecords.at(8)["id"]); + REQUIRE(matrix1DDimensionListsRecords.at(0)["dim_order"] == "0"); + REQUIRE(matrix1DDimensionListsRecords.at(0)["upper_bound"] == "1"); - REQUIRE(remove("./test_db.sqlite")==0); + REQUIRE(remove("./test_db.sqlite") == 0); delete idc; } -TEST_CASE("Write keys to database that already exist" ,"[main_test#5]") +TEST_CASE("Write keys to database that already exist", "[main_test#5]") { Juicer juicer; IDataContainer* idc = 0; @@ -1093,9 +1280,8 @@ TEST_CASE("Write keys to database that already exist" ,"[main_test#5]") std::string inputFile{TEST_FILE_1}; - idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); - REQUIRE(idc!=nullptr); + REQUIRE(idc != nullptr); logger.logInfo("IDataContainer was constructed successfully for unit test."); juicer.setIDC(idc); @@ -1110,9 +1296,8 @@ TEST_CASE("Write keys to database that already exist" ,"[main_test#5]") *Clean up our database handle and objects in memory. */ ((SQLiteDB*)(idc))->close(); - REQUIRE(remove("./test_db.sqlite")==0); + REQUIRE(remove("./test_db.sqlite") == 0); delete idc; - } // TEST_CASE("Write Elf File to database with a log file", "[main_test#6]") @@ -1125,23 +1310,24 @@ TEST_CASE("Write Elf File to database with a log file", "[main_test#6]") std::string inputFile{TEST_FILE_1}; - idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); - REQUIRE(idc!=nullptr); - logger.logInfo("IDataContainer was constructed successfully for unit test."); + idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); + REQUIRE(idc != nullptr); + logger.logInfo("IDataContainer was constructed successfully for unit test."); - juicer.setIDC(idc); + juicer.setIDC(idc); - REQUIRE(juicer.parse(inputFile)==JUICER_OK); + REQUIRE(juicer.parse(inputFile) == JUICER_OK); - logger.setLogFile("logFile"); + logger.setLogFile("logFile"); - /** - *Clean up our database handle and objects in memory. - */ - ((SQLiteDB*)(idc))->close(); - delete idc; - REQUIRE(remove("./logFile")==0); - REQUIRE(remove("./test_db.sqlite")==0); + /** + *Clean up our database handle and objects in memory. + */ + ((SQLiteDB*)(idc))->close(); + delete idc; + // Logger::instance->closeLogFile(); + REQUIRE(remove("./logFile") == 0); + REQUIRE(remove("./test_db.sqlite") == 0); } TEST_CASE("Write Elf File to database with verbosity set to INFO", "[main_test#7]") @@ -1150,21 +1336,23 @@ TEST_CASE("Write Elf File to database with verbosity set to INFO", "[main_test#7 IDataContainer* idc = 0; Logger logger{LOGGER_VERBOSITY_INFO}; - std::string inputFile{TEST_FILE_1}; + std::string inputFile{TEST_FILE_1}; + + idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); + REQUIRE(idc != nullptr); + logger.logInfo("IDataContainer was constructed successfully for unit test."); - idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); - REQUIRE(idc!=nullptr); - logger.logInfo("IDataContainer was constructed successfully for unit test."); + juicer.setIDC(idc); + juicer.parse(inputFile); - juicer.setIDC(idc); - juicer.parse(inputFile); + REQUIRE((juicer.getDwarfVersion() == 4 || juicer.getDwarfVersion() == 5)); - /** - *Clean up our database handle and objects in memory. - */ - ((SQLiteDB*)(idc))->close(); - delete idc; - REQUIRE(remove("./test_db.sqlite")==0); + /** + *Clean up our database handle and objects in memory. + */ + ((SQLiteDB*)(idc))->close(); + delete idc; + REQUIRE(remove("./test_db.sqlite") == 0); } TEST_CASE("Write Elf File to database with invalid verbosity", "[main_test#8]") @@ -1177,18 +1365,1976 @@ TEST_CASE("Write Elf File to database with invalid verbosity", "[main_test#8]") std::string inputFile{TEST_FILE_1}; - idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); - REQUIRE(idc!=nullptr); - logger.logInfo("IDataContainer was constructed successfully for unit test."); + idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); + REQUIRE(idc != nullptr); + logger.logInfo("IDataContainer was constructed successfully for unit test."); + + juicer.setIDC(idc); + juicer.parse(inputFile); - juicer.setIDC(idc); - juicer.parse(inputFile); + REQUIRE((juicer.getDwarfVersion() == 4 || juicer.getDwarfVersion() == 5)); - /** - *Clean up our database handle and objects in memory. - */ - ((SQLiteDB*)(idc))->close(); - delete idc; - REQUIRE(remove("./test_db.sqlite")==0); + /** + *Clean up our database handle and objects in memory. + */ + ((SQLiteDB*)(idc))->close(); + delete idc; + REQUIRE(remove("./test_db.sqlite") == 0); } +TEST_CASE( + "Test the correctness of the CFE_ES_HousekeepingTlm_Payload_t struct after Juicer has processed it. " + "This also tests the \"extras\" features such as ELF image data.", + "[main_test#9]") +{ + /** + * 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_1}; + + idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); + REQUIRE(idc != nullptr); + logger.logInfo("IDataContainer was constructed successfully for unit test."); + + juicer.setIDC(idc); + juicer.setExtras(true); + + rc = juicer.parse(inputFile); + + REQUIRE((juicer.getDwarfVersion() == 4 || juicer.getDwarfVersion() == 5)); + + REQUIRE(rc == JUICER_OK); + + std::string getSquareStructQuery{"SELECT * FROM symbols WHERE name = \"CFE_ES_HousekeepingTlm_Payload_t\"; "}; + + /** + *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> hkRecords{}; + + rc = sqlite3_exec(database, getSquareStructQuery.c_str(), selectCallbackUsingColNameAsKey, &hkRecords, &errorMessage); + + REQUIRE(rc == SQLITE_OK); + REQUIRE(hkRecords.size() == 1); + + uint32_t numberOfColumns = 0; + + for (auto pair : hkRecords.at(0)) + { + numberOfColumns++; + } + + REQUIRE(numberOfColumns == 9); + + /** + * Check the correctness of Square struct. + */ + + REQUIRE(hkRecords.at(0)["name"] == "CFE_ES_HousekeepingTlm_Payload_t"); + + REQUIRE(hkRecords.at(0)["target_symbol"] != "NULL"); + REQUIRE(hkRecords.at(0)["byte_size"] == std::to_string(sizeof(CFE_ES_HousekeepingTlm_Payload_t))); + + std::string hkTargetSymbolId = followTargetSymbol(database, hkRecords.at(0)["id"]).at("id"); + + std::string squareArtifactId = hkRecords.at(0)["artifact"]; + + REQUIRE(!squareArtifactId.empty()); + + std::string getSquareArtifact{"SELECT * FROM artifacts WHERE id = "}; + + getSquareArtifact += squareArtifactId; + getSquareArtifact += ";"; + + std::vector> squareArtifactRecords{}; + + rc = sqlite3_exec(database, getSquareArtifact.c_str(), selectCallbackUsingColNameAsKey, &squareArtifactRecords, &errorMessage); + + REQUIRE(squareArtifactRecords.size() == 1); + + std::string path{}; + char resolvedPath[PATH_MAX]; + + realpath("../unit-test/test_file1.h", resolvedPath); + + path.clear(); + path.insert(0, resolvedPath); + + REQUIRE(squareArtifactRecords.at(0)["path"] == path); + + std::string expectedMD5Str = getmd5sumFromSystem(resolvedPath); + REQUIRE(expectedMD5Str == squareArtifactRecords.at(0)["md5"]); + + std::string getHKFields{"SELECT * FROM fields WHERE symbol = "}; + + getHKFields += hkTargetSymbolId; + getHKFields += ";"; + + std::vector> hkFieldsRecords{}; + + rc = sqlite3_exec(database, getHKFields.c_str(), selectCallbackUsingColNameAsKey, &hkFieldsRecords, &errorMessage); + + REQUIRE(rc == SQLITE_OK); + REQUIRE(hkFieldsRecords.size() == 42); + + // Enforce order of records by offset + std::sort(hkFieldsRecords.begin(), hkFieldsRecords.end(), [](std::map a, std::map b) + { return std::stoi(a["byte_offset"]) < std::stoi(b["byte_offset"]); }); + + std::string getCommandCounterType{"SELECT * FROM symbols where id="}; + getCommandCounterType += hkFieldsRecords.at(0)["type"]; + getCommandCounterType += ";"; + + std::vector> CommandCounterTypeRecords{}; + + rc = sqlite3_exec(database, getCommandCounterType.c_str(), selectCallbackUsingColNameAsKey, &CommandCounterTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(CommandCounterTypeRecords.size() == 1); + + std::string widthType{CommandCounterTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(0)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(0)["name"] == "CommandCounter"); + REQUIRE(hkFieldsRecords.at(0)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, CommandCounter))); + REQUIRE(hkFieldsRecords.at(0)["type"] == widthType); + REQUIRE(hkFieldsRecords.at(0)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(0)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(0)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(0)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(0)["long_description"] == ""); + + std::string getCommandErrorCounterType{"SELECT * FROM symbols where id="}; + getCommandErrorCounterType += hkFieldsRecords.at(1)["type"]; + getCommandErrorCounterType += ";"; + + std::vector> CommandErrorCounterTypeRecords{}; + + rc = sqlite3_exec(database, getCommandErrorCounterType.c_str(), selectCallbackUsingColNameAsKey, &CommandErrorCounterTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(CommandErrorCounterTypeRecords.size() == 1); + + std::string CommandErrorCounterType{CommandErrorCounterTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(1)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(1)["name"] == "CommandErrorCounter"); + REQUIRE(hkFieldsRecords.at(1)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, CommandErrorCounter))); + REQUIRE(hkFieldsRecords.at(1)["type"] == CommandErrorCounterType); + REQUIRE(hkFieldsRecords.at(1)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(1)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(1)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(1)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(1)["long_description"] == ""); + + std::string getCFECoreChecksumTypeType{"SELECT * FROM symbols where id="}; + getCFECoreChecksumTypeType += hkFieldsRecords.at(2)["type"]; + getCFECoreChecksumTypeType += ";"; + + std::vector> CFECoreChecksumTypeTypeRecords{}; + + rc = sqlite3_exec(database, getCFECoreChecksumTypeType.c_str(), selectCallbackUsingColNameAsKey, &CFECoreChecksumTypeTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(CFECoreChecksumTypeTypeRecords.size() == 1); + + std::string CFECoreChecksumType{CFECoreChecksumTypeTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(2)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(2)["name"] == "CFECoreChecksum"); + REQUIRE(hkFieldsRecords.at(2)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, CFECoreChecksum))); + REQUIRE(hkFieldsRecords.at(2)["type"] == CFECoreChecksumType); + REQUIRE(hkFieldsRecords.at(2)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(2)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(2)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(2)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(2)["long_description"] == ""); + + std::string getCFEMajorVersionType{"SELECT * FROM symbols where id="}; + getCFEMajorVersionType += hkFieldsRecords.at(3)["type"]; + getCFEMajorVersionType += ";"; + + std::vector> CFEMajorVersionTypeRecords{}; + + rc = sqlite3_exec(database, getCFEMajorVersionType.c_str(), selectCallbackUsingColNameAsKey, &CFEMajorVersionTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(CFEMajorVersionTypeRecords.size() == 1); + + std::string CFEMajorVersionType{CFEMajorVersionTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(3)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(3)["name"] == "CFEMajorVersion"); + REQUIRE(hkFieldsRecords.at(3)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, CFEMajorVersion))); + REQUIRE(hkFieldsRecords.at(3)["type"] == CFEMajorVersionType); + REQUIRE(hkFieldsRecords.at(3)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(3)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(3)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(3)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(3)["long_description"] == ""); + + std::string getMoreStuffType{"SELECT * FROM symbols where id="}; + getMoreStuffType += hkFieldsRecords.at(4)["type"]; + getMoreStuffType += ";"; + + std::vector> CFEMinorVersionTypeTypeRecords{}; + + rc = sqlite3_exec(database, getMoreStuffType.c_str(), selectCallbackUsingColNameAsKey, &CFEMinorVersionTypeTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(CFEMinorVersionTypeTypeRecords.size() == 1); + + std::string CFEMinorVersionType{CFEMinorVersionTypeTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(4)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(4)["name"] == "CFEMinorVersion"); + REQUIRE(hkFieldsRecords.at(4)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, CFEMinorVersion))); + REQUIRE(hkFieldsRecords.at(4)["type"] == CFEMinorVersionType); + REQUIRE(hkFieldsRecords.at(4)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(4)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(4)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(4)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(4)["long_description"] == ""); + + std::string getPadding2Type{"SELECT * FROM symbols where id="}; + getPadding2Type += hkFieldsRecords.at(5)["type"]; + getPadding2Type += ";"; + + std::vector> padding2TypeRecords{}; + + rc = sqlite3_exec(database, getPadding2Type.c_str(), selectCallbackUsingColNameAsKey, &padding2TypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(padding2TypeRecords.size() == 1); + + std::string padding2Type{padding2TypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(5)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(5)["name"] == "CFERevision"); + REQUIRE(hkFieldsRecords.at(5)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, CFERevision))); + REQUIRE(hkFieldsRecords.at(5)["type"] == padding2Type); + REQUIRE(hkFieldsRecords.at(5)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(5)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(5)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(5)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(5)["long_description"] == ""); + + std::string getCFEMissionRevisioType{"SELECT * FROM symbols where id="}; + getCFEMissionRevisioType += hkFieldsRecords.at(6)["type"]; + getCFEMissionRevisioType += ";"; + + std::vector> CFEMissionRevisionTypeRecords{}; + + rc = sqlite3_exec(database, getCFEMissionRevisioType.c_str(), selectCallbackUsingColNameAsKey, &CFEMissionRevisionTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(CFEMissionRevisionTypeRecords.size() == 1); + + std::string CFEMissionRevisionType{CFEMissionRevisionTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(6)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(6)["name"] == "CFEMissionRevision"); + REQUIRE(hkFieldsRecords.at(6)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, CFEMissionRevision))); + REQUIRE(hkFieldsRecords.at(6)["type"] == CFEMissionRevisionType); + REQUIRE(hkFieldsRecords.at(6)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(6)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(6)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(6)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(6)["long_description"] == ""); + + std::string getOSALMajorVersionType{"SELECT * FROM symbols where id="}; + getOSALMajorVersionType += hkFieldsRecords.at(7)["type"]; + getOSALMajorVersionType += ";"; + + std::vector> OSALMajorVersionTypeRecords{}; + + rc = sqlite3_exec(database, getOSALMajorVersionType.c_str(), selectCallbackUsingColNameAsKey, &OSALMajorVersionTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(OSALMajorVersionTypeRecords.size() == 1); + + std::string OSALMajorVersionType{OSALMajorVersionTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(7)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(7)["name"] == "OSALMajorVersion"); + REQUIRE(hkFieldsRecords.at(7)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, OSALMajorVersion))); + REQUIRE(hkFieldsRecords.at(7)["type"] == OSALMajorVersionType); + REQUIRE(hkFieldsRecords.at(7)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(7)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(7)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(7)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(7)["long_description"] == ""); + + std::string getOSALMinorVersionType{"SELECT * FROM symbols where id="}; + getOSALMinorVersionType += hkFieldsRecords.at(8)["type"]; + getOSALMinorVersionType += ";"; + + std::vector> OSALMinorVersionTypeRecords{}; + + rc = sqlite3_exec(database, getOSALMinorVersionType.c_str(), selectCallbackUsingColNameAsKey, &OSALMinorVersionTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(OSALMinorVersionTypeRecords.size() == 1); + + std::string OSALMinorVersionType{OSALMinorVersionTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(8)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(8)["name"] == "OSALMinorVersion"); + REQUIRE(hkFieldsRecords.at(8)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, OSALMinorVersion))); + REQUIRE(hkFieldsRecords.at(8)["type"] == OSALMinorVersionType); + REQUIRE(hkFieldsRecords.at(8)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(8)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(8)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(8)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(8)["long_description"] == ""); + + std::string getOSALRevisionType{"SELECT * FROM symbols where id="}; + getOSALRevisionType += hkFieldsRecords.at(9)["type"]; + getOSALRevisionType += ";"; + + std::vector> OSALRevisionTypeRecords{}; + + rc = sqlite3_exec(database, getOSALRevisionType.c_str(), selectCallbackUsingColNameAsKey, &OSALRevisionTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(OSALRevisionTypeRecords.size() == 1); + + std::string OSALRevisionType{OSALRevisionTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(9)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(9)["name"] == "OSALRevision"); + REQUIRE(hkFieldsRecords.at(9)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, OSALRevision))); + REQUIRE(hkFieldsRecords.at(9)["type"] == OSALRevisionType); + REQUIRE(hkFieldsRecords.at(9)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(9)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(9)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(9)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(9)["long_description"] == ""); + + std::string getOSALMissionRevisionType{"SELECT * FROM symbols where id="}; + getOSALMissionRevisionType += hkFieldsRecords.at(10)["type"]; + getOSALMissionRevisionType += ";"; + + std::vector> OSALMissionRevisionTypeRecords{}; + + rc = sqlite3_exec(database, getOSALMissionRevisionType.c_str(), selectCallbackUsingColNameAsKey, &OSALMissionRevisionTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(OSALMissionRevisionTypeRecords.size() == 1); + + std::string OSALMissionRevisionType{OSALMissionRevisionTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(10)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(10)["name"] == "OSALMissionRevision"); + REQUIRE(hkFieldsRecords.at(10)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, OSALMissionRevision))); + REQUIRE(hkFieldsRecords.at(10)["type"] == OSALMissionRevisionType); + REQUIRE(hkFieldsRecords.at(10)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(10)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(10)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(10)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(10)["long_description"] == ""); + + std::string getPSPMajorVersionType{"SELECT * FROM symbols where id="}; + getPSPMajorVersionType += hkFieldsRecords.at(11)["type"]; + getPSPMajorVersionType += ";"; + + std::vector> PSPMajorVersionTypeRecords{}; + + rc = sqlite3_exec(database, getPSPMajorVersionType.c_str(), selectCallbackUsingColNameAsKey, &PSPMajorVersionTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(PSPMajorVersionTypeRecords.size() == 1); + + std::string PSPMajorVersionType{PSPMajorVersionTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(11)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(11)["name"] == "PSPMajorVersion"); + REQUIRE(hkFieldsRecords.at(11)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, PSPMajorVersion))); + REQUIRE(hkFieldsRecords.at(11)["type"] == PSPMajorVersionType); + REQUIRE(hkFieldsRecords.at(11)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(11)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(11)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(11)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(11)["long_description"] == ""); + + std::string getPSPMinorVersionType{"SELECT * FROM symbols where id="}; + getPSPMinorVersionType += hkFieldsRecords.at(12)["type"]; + getPSPMinorVersionType += ";"; + + std::vector> PSPMinorVersionTypeRecords{}; + + rc = sqlite3_exec(database, getPSPMinorVersionType.c_str(), selectCallbackUsingColNameAsKey, &PSPMinorVersionTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(PSPMinorVersionTypeRecords.size() == 1); + + std::string PSPMinorVersionType{PSPMinorVersionTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(12)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(12)["name"] == "PSPMinorVersion"); + REQUIRE(hkFieldsRecords.at(12)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, PSPMinorVersion))); + REQUIRE(hkFieldsRecords.at(12)["type"] == PSPMinorVersionType); + REQUIRE(hkFieldsRecords.at(12)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(12)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(12)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(12)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(12)["long_description"] == ""); + + std::string getPSPRevisionType{"SELECT * FROM symbols where id="}; + getPSPRevisionType += hkFieldsRecords.at(13)["type"]; + getPSPRevisionType += ";"; + + std::vector> PSPRevisionTypeRecords{}; + + rc = sqlite3_exec(database, getPSPRevisionType.c_str(), selectCallbackUsingColNameAsKey, &PSPRevisionTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(PSPRevisionTypeRecords.size() == 1); + + std::string PSPRevisionType{PSPRevisionTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(13)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(13)["name"] == "PSPRevision"); + REQUIRE(hkFieldsRecords.at(13)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, PSPRevision))); + REQUIRE(hkFieldsRecords.at(13)["type"] == PSPRevisionType); + REQUIRE(hkFieldsRecords.at(13)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(13)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(13)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(13)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(13)["long_description"] == ""); + + std::string getPSPMissionRevisionType{"SELECT * FROM symbols where id="}; + getPSPMissionRevisionType += hkFieldsRecords.at(14)["type"]; + getPSPMissionRevisionType += ";"; + + std::vector> PSPMissionRevisionTypeRecords{}; + + rc = sqlite3_exec(database, getPSPMissionRevisionType.c_str(), selectCallbackUsingColNameAsKey, &PSPMissionRevisionTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(PSPMissionRevisionTypeRecords.size() == 1); + + std::string PSPMissionRevisionType{PSPMissionRevisionTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(14)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(14)["name"] == "PSPMissionRevision"); + REQUIRE(hkFieldsRecords.at(14)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, PSPMissionRevision))); + REQUIRE(hkFieldsRecords.at(14)["type"] == PSPMissionRevisionType); + REQUIRE(hkFieldsRecords.at(14)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(14)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(14)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(14)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(14)["long_description"] == ""); + + std::string getSysLogBytesUsedType{"SELECT * FROM symbols where id="}; + getSysLogBytesUsedType += hkFieldsRecords.at(15)["type"]; + getSysLogBytesUsedType += ";"; + + std::vector> SysLogBytesUsedTypeRecords{}; + + rc = sqlite3_exec(database, getSysLogBytesUsedType.c_str(), selectCallbackUsingColNameAsKey, &SysLogBytesUsedTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(SysLogBytesUsedTypeRecords.size() == 1); + + std::string SysLogBytesUsedType{SysLogBytesUsedTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(15)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(15)["name"] == "SysLogBytesUsed"); + REQUIRE(hkFieldsRecords.at(15)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, SysLogBytesUsed))); + REQUIRE(hkFieldsRecords.at(15)["type"] == SysLogBytesUsedType); + REQUIRE(hkFieldsRecords.at(15)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(15)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(15)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(15)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(15)["long_description"] == ""); + + std::string getSysLogSizeType{"SELECT * FROM symbols where id="}; + getSysLogSizeType += hkFieldsRecords.at(16)["type"]; + getSysLogSizeType += ";"; + + std::vector> SysLogSizeTypeRecords{}; + + rc = sqlite3_exec(database, getSysLogSizeType.c_str(), selectCallbackUsingColNameAsKey, &SysLogSizeTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(SysLogSizeTypeRecords.size() == 1); + + std::string SysLogSizeType{SysLogSizeTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(16)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(16)["name"] == "SysLogSize"); + REQUIRE(hkFieldsRecords.at(16)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, SysLogSize))); + REQUIRE(hkFieldsRecords.at(16)["type"] == SysLogSizeType); + REQUIRE(hkFieldsRecords.at(16)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(16)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(16)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(16)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(16)["long_description"] == ""); + + std::string getSysLogEntriesType{"SELECT * FROM symbols where id="}; + getSysLogEntriesType += hkFieldsRecords.at(17)["type"]; + getSysLogEntriesType += ";"; + + std::vector> SysLogEntriesTypeRecords{}; + + rc = sqlite3_exec(database, getSysLogEntriesType.c_str(), selectCallbackUsingColNameAsKey, &SysLogEntriesTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(SysLogEntriesTypeRecords.size() == 1); + + std::string SysLogEntriesType{SysLogEntriesTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(17)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(17)["name"] == "SysLogEntries"); + REQUIRE(hkFieldsRecords.at(17)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, SysLogEntries))); + REQUIRE(hkFieldsRecords.at(17)["type"] == SysLogEntriesType); + REQUIRE(hkFieldsRecords.at(17)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(17)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(17)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(17)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(17)["long_description"] == ""); + + std::string getSysLogModeType{"SELECT * FROM symbols where id="}; + getSysLogModeType += hkFieldsRecords.at(18)["type"]; + getSysLogModeType += ";"; + + std::vector> SysLogModeTypeRecords{}; + + rc = sqlite3_exec(database, getSysLogModeType.c_str(), selectCallbackUsingColNameAsKey, &SysLogModeTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(SysLogModeTypeRecords.size() == 1); + + std::string SysLogModeType{SysLogModeTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(18)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(18)["name"] == "SysLogMode"); + REQUIRE(hkFieldsRecords.at(18)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, SysLogMode))); + REQUIRE(hkFieldsRecords.at(18)["type"] == SysLogModeType); + REQUIRE(hkFieldsRecords.at(18)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(18)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(18)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(18)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(18)["long_description"] == ""); + + std::string getERLogIndexType{"SELECT * FROM symbols where id="}; + getERLogIndexType += hkFieldsRecords.at(19)["type"]; + getERLogIndexType += ";"; + + std::vector> ERLogIndexTypeRecords{}; + + rc = sqlite3_exec(database, getERLogIndexType.c_str(), selectCallbackUsingColNameAsKey, &ERLogIndexTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(ERLogIndexTypeRecords.size() == 1); + + std::string ERLogIndexType{ERLogIndexTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(19)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(19)["name"] == "ERLogIndex"); + REQUIRE(hkFieldsRecords.at(19)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, ERLogIndex))); + REQUIRE(hkFieldsRecords.at(19)["type"] == ERLogIndexType); + REQUIRE(hkFieldsRecords.at(19)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(19)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(19)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(19)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(19)["long_description"] == ""); + + std::string getERLogEntriesType{"SELECT * FROM symbols where id="}; + getERLogEntriesType += hkFieldsRecords.at(20)["type"]; + getERLogEntriesType += ";"; + + std::vector> ERLogEntriesTypeRecords{}; + + rc = sqlite3_exec(database, getERLogEntriesType.c_str(), selectCallbackUsingColNameAsKey, &ERLogEntriesTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(ERLogEntriesTypeRecords.size() == 1); + + std::string ERLogEntriesType{ERLogEntriesTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(20)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(20)["name"] == "ERLogEntries"); + REQUIRE(hkFieldsRecords.at(20)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, ERLogEntries))); + REQUIRE(hkFieldsRecords.at(20)["type"] == ERLogEntriesType); + REQUIRE(hkFieldsRecords.at(20)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(20)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(20)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(20)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(20)["long_description"] == ""); + + std::string getRegisteredCoreAppsType{"SELECT * FROM symbols where id="}; + getRegisteredCoreAppsType += hkFieldsRecords.at(21)["type"]; + getRegisteredCoreAppsType += ";"; + + std::vector> RegisteredCoreAppsTypeRecords{}; + + rc = sqlite3_exec(database, getRegisteredCoreAppsType.c_str(), selectCallbackUsingColNameAsKey, &RegisteredCoreAppsTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(RegisteredCoreAppsTypeRecords.size() == 1); + + std::string RegisteredCoreAppsType{RegisteredCoreAppsTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(21)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(21)["name"] == "RegisteredCoreApps"); + REQUIRE(hkFieldsRecords.at(21)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, RegisteredCoreApps))); + REQUIRE(hkFieldsRecords.at(21)["type"] == RegisteredCoreAppsType); + REQUIRE(hkFieldsRecords.at(21)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(21)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(21)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(21)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(21)["long_description"] == ""); + + std::string getRegisteredExternalAppsType{"SELECT * FROM symbols where id="}; + getRegisteredExternalAppsType += hkFieldsRecords.at(22)["type"]; + getRegisteredExternalAppsType += ";"; + + std::vector> RegisteredExternalAppsTypeRecords{}; + + rc = sqlite3_exec(database, getRegisteredExternalAppsType.c_str(), selectCallbackUsingColNameAsKey, &RegisteredExternalAppsTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(RegisteredExternalAppsTypeRecords.size() == 1); + + std::string RegisteredExternalAppsType{RegisteredExternalAppsTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(22)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(22)["name"] == "RegisteredExternalApps"); + REQUIRE(hkFieldsRecords.at(22)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, RegisteredExternalApps))); + REQUIRE(hkFieldsRecords.at(22)["type"] == RegisteredExternalAppsType); + REQUIRE(hkFieldsRecords.at(22)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(22)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(22)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(22)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(22)["long_description"] == ""); + + std::string getRegisteredTasksType{"SELECT * FROM symbols where id="}; + getRegisteredTasksType += hkFieldsRecords.at(23)["type"]; + getRegisteredTasksType += ";"; + + std::vector> RegisteredTasksTypeRecords{}; + + rc = sqlite3_exec(database, getRegisteredTasksType.c_str(), selectCallbackUsingColNameAsKey, &RegisteredTasksTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(RegisteredTasksTypeRecords.size() == 1); + + std::string RegisteredTasksType{RegisteredTasksTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(23)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(23)["name"] == "RegisteredTasks"); + REQUIRE(hkFieldsRecords.at(23)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, RegisteredTasks))); + REQUIRE(hkFieldsRecords.at(23)["type"] == RegisteredTasksType); + REQUIRE(hkFieldsRecords.at(23)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(23)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(23)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(23)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(23)["long_description"] == ""); + + std::string getRegisteredLibsType{"SELECT * FROM symbols where id="}; + getRegisteredLibsType += hkFieldsRecords.at(24)["type"]; + getRegisteredLibsType += ";"; + + std::vector> RegisteredLibsTypeRecords{}; + + rc = sqlite3_exec(database, getRegisteredLibsType.c_str(), selectCallbackUsingColNameAsKey, &RegisteredLibsTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(RegisteredLibsTypeRecords.size() == 1); + + std::string RegisteredLibsType{RegisteredLibsTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(24)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(24)["name"] == "RegisteredLibs"); + REQUIRE(hkFieldsRecords.at(24)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, RegisteredLibs))); + REQUIRE(hkFieldsRecords.at(24)["type"] == RegisteredLibsType); + REQUIRE(hkFieldsRecords.at(24)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(24)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(24)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(24)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(24)["long_description"] == ""); + + std::string getResetTypeType{"SELECT * FROM symbols where id="}; + getResetTypeType += hkFieldsRecords.at(25)["type"]; + getResetTypeType += ";"; + + std::vector> ResetTypeTypeRecords{}; + + rc = sqlite3_exec(database, getResetTypeType.c_str(), selectCallbackUsingColNameAsKey, &ResetTypeTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(ResetTypeTypeRecords.size() == 1); + + std::string ResetTypeType{ResetTypeTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(25)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(25)["name"] == "ResetType"); + REQUIRE(hkFieldsRecords.at(25)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, ResetType))); + REQUIRE(hkFieldsRecords.at(25)["type"] == ResetTypeType); + REQUIRE(hkFieldsRecords.at(25)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(25)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(25)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(25)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(25)["long_description"] == ""); + + std::string getResetSubtypeType{"SELECT * FROM symbols where id="}; + getResetSubtypeType += hkFieldsRecords.at(26)["type"]; + getResetSubtypeType += ";"; + + std::vector> ResetSubtypeTypeRecords{}; + + rc = sqlite3_exec(database, getResetSubtypeType.c_str(), selectCallbackUsingColNameAsKey, &ResetSubtypeTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(ResetSubtypeTypeRecords.size() == 1); + + std::string ResetSubtypeType{ResetSubtypeTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(26)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(26)["name"] == "ResetSubtype"); + REQUIRE(hkFieldsRecords.at(26)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, ResetSubtype))); + REQUIRE(hkFieldsRecords.at(26)["type"] == ResetSubtypeType); + REQUIRE(hkFieldsRecords.at(26)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(26)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(26)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(26)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(26)["long_description"] == ""); + + std::string getProcessorResetsType{"SELECT * FROM symbols where id="}; + getProcessorResetsType += hkFieldsRecords.at(27)["type"]; + getProcessorResetsType += ";"; + + std::vector> ProcessorResetsTypeRecords{}; + + rc = sqlite3_exec(database, getProcessorResetsType.c_str(), selectCallbackUsingColNameAsKey, &ProcessorResetsTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(ProcessorResetsTypeRecords.size() == 1); + + std::string ProcessorResetsType{ProcessorResetsTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(27)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(27)["name"] == "ProcessorResets"); + REQUIRE(hkFieldsRecords.at(27)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, ProcessorResets))); + REQUIRE(hkFieldsRecords.at(27)["type"] == ProcessorResetsType); + REQUIRE(hkFieldsRecords.at(27)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(27)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(27)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(27)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(27)["long_description"] == ""); + + std::string getMaxProcessorResetsType{"SELECT * FROM symbols where id="}; + getMaxProcessorResetsType += hkFieldsRecords.at(28)["type"]; + getMaxProcessorResetsType += ";"; + + std::vector> MaxProcessorResetsTypeRecords{}; + + rc = sqlite3_exec(database, getMaxProcessorResetsType.c_str(), selectCallbackUsingColNameAsKey, &MaxProcessorResetsTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(MaxProcessorResetsTypeRecords.size() == 1); + + std::string MaxProcessorResetsType{MaxProcessorResetsTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(28)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(28)["name"] == "MaxProcessorResets"); + REQUIRE(hkFieldsRecords.at(28)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, MaxProcessorResets))); + REQUIRE(hkFieldsRecords.at(28)["type"] == MaxProcessorResetsType); + REQUIRE(hkFieldsRecords.at(28)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(28)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(28)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(28)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(28)["long_description"] == ""); + + std::string getBootSourceType{"SELECT * FROM symbols where id="}; + getBootSourceType += hkFieldsRecords.at(29)["type"]; + getBootSourceType += ";"; + + std::vector> BootSourceTypeRecords{}; + + rc = sqlite3_exec(database, getBootSourceType.c_str(), selectCallbackUsingColNameAsKey, &BootSourceTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(BootSourceTypeRecords.size() == 1); + + std::string BootSourceType{BootSourceTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(29)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(29)["name"] == "BootSource"); + REQUIRE(hkFieldsRecords.at(29)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, BootSource))); + REQUIRE(hkFieldsRecords.at(29)["type"] == BootSourceType); + REQUIRE(hkFieldsRecords.at(29)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(29)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(29)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(29)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(29)["long_description"] == ""); + + std::string getPerfStateType{"SELECT * FROM symbols where id="}; + getPerfStateType += hkFieldsRecords.at(30)["type"]; + getPerfStateType += ";"; + + std::vector> PerfStateTypeRecords{}; + + rc = sqlite3_exec(database, getPerfStateType.c_str(), selectCallbackUsingColNameAsKey, &PerfStateTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(PerfStateTypeRecords.size() == 1); + + std::string PerfStateType{PerfStateTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(30)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(30)["name"] == "PerfState"); + REQUIRE(hkFieldsRecords.at(30)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, PerfState))); + REQUIRE(hkFieldsRecords.at(30)["type"] == PerfStateType); + REQUIRE(hkFieldsRecords.at(30)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(30)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(30)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(30)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(30)["long_description"] == ""); + + std::string getPerfModeType{"SELECT * FROM symbols where id="}; + getPerfModeType += hkFieldsRecords.at(31)["type"]; + getPerfModeType += ";"; + + std::vector> PerfModeTypeRecords{}; + + rc = sqlite3_exec(database, getPerfModeType.c_str(), selectCallbackUsingColNameAsKey, &PerfModeTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(PerfModeTypeRecords.size() == 1); + + std::string PerfModeType{PerfModeTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(31)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(31)["name"] == "PerfMode"); + REQUIRE(hkFieldsRecords.at(31)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, PerfMode))); + REQUIRE(hkFieldsRecords.at(31)["type"] == PerfModeType); + REQUIRE(hkFieldsRecords.at(31)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(31)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(31)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(31)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(31)["long_description"] == ""); + + std::string getPerfTriggerCountType{"SELECT * FROM symbols where id="}; + getPerfTriggerCountType += hkFieldsRecords.at(32)["type"]; + getPerfTriggerCountType += ";"; + + std::vector> PerfTriggerCountTypeRecords{}; + + rc = sqlite3_exec(database, getPerfTriggerCountType.c_str(), selectCallbackUsingColNameAsKey, &PerfTriggerCountTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(PerfTriggerCountTypeRecords.size() == 1); + + std::string PerfTriggerCountType{PerfTriggerCountTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(32)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(32)["name"] == "PerfTriggerCount"); + REQUIRE(hkFieldsRecords.at(32)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, PerfTriggerCount))); + REQUIRE(hkFieldsRecords.at(32)["type"] == PerfTriggerCountType); + REQUIRE(hkFieldsRecords.at(32)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(32)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(32)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(32)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(32)["long_description"] == ""); + + std::string getPerfFilterMaskType{"SELECT * FROM symbols where id="}; + getPerfFilterMaskType += hkFieldsRecords.at(33)["type"]; + getPerfFilterMaskType += ";"; + + std::vector> PerfFilterMaskTypeRecords{}; + + rc = sqlite3_exec(database, getPerfFilterMaskType.c_str(), selectCallbackUsingColNameAsKey, &PerfFilterMaskTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(PerfFilterMaskTypeRecords.size() == 1); + + std::string PerfFilterMaskType{PerfFilterMaskTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(33)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(33)["name"] == "PerfFilterMask"); + REQUIRE(hkFieldsRecords.at(33)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, PerfFilterMask))); + REQUIRE(hkFieldsRecords.at(33)["type"] == PerfFilterMaskType); + REQUIRE(hkFieldsRecords.at(33)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(33)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(33)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(33)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(33)["long_description"] == ""); + + std::string getDimensionLists{"SELECT * FROM dimension_lists WHERE field_id="}; + getDimensionLists += hkFieldsRecords.at(33)["id"]; + getDimensionLists += ";"; + + std::vector> DimensionListsRecords{}; + + rc = sqlite3_exec(database, getDimensionLists.c_str(), selectCallbackUsingColNameAsKey, &DimensionListsRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(DimensionListsRecords.size() == 1); + + // Enforce order of records by dim_order + std::sort(DimensionListsRecords.begin(), DimensionListsRecords.end(), + [](std::map a, std::map b) { return std::stoi(a["dim_order"]) < std::stoi(b["dim_order"]); }); + + REQUIRE(DimensionListsRecords.at(0)["field_id"] == hkFieldsRecords.at(33)["id"]); + REQUIRE(DimensionListsRecords.at(0)["dim_order"] == "0"); + REQUIRE(DimensionListsRecords.at(0)["upper_bound"] == "3"); + + std::string getPerfTriggerMaskType{"SELECT * FROM symbols where id="}; + getPerfTriggerMaskType += hkFieldsRecords.at(34)["type"]; + getPerfTriggerMaskType += ";"; + + std::vector> PerfTriggerMaskTypeRecords{}; + + rc = sqlite3_exec(database, getPerfTriggerMaskType.c_str(), selectCallbackUsingColNameAsKey, &PerfTriggerMaskTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(PerfTriggerMaskTypeRecords.size() == 1); + + std::string PerfTriggerMaskType{PerfTriggerMaskTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(34)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(34)["name"] == "PerfTriggerMask"); + REQUIRE(hkFieldsRecords.at(34)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, PerfTriggerMask))); + REQUIRE(hkFieldsRecords.at(34)["type"] == PerfTriggerMaskType); + REQUIRE(hkFieldsRecords.at(34)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(34)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(34)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(34)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(34)["long_description"] == ""); + + getDimensionLists = "SELECT * FROM dimension_lists WHERE field_id="; + getDimensionLists += hkFieldsRecords.at(34)["id"]; + getDimensionLists += ";"; + + DimensionListsRecords.clear(); + + rc = sqlite3_exec(database, getDimensionLists.c_str(), selectCallbackUsingColNameAsKey, &DimensionListsRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(DimensionListsRecords.size() == 1); + + // Enforce order of records by dim_order + std::sort(DimensionListsRecords.begin(), DimensionListsRecords.end(), + [](std::map a, std::map b) { return std::stoi(a["dim_order"]) < std::stoi(b["dim_order"]); }); + + REQUIRE(DimensionListsRecords.at(0)["field_id"] == hkFieldsRecords.at(34)["id"]); + REQUIRE(DimensionListsRecords.at(0)["dim_order"] == "0"); + REQUIRE(DimensionListsRecords.at(0)["upper_bound"] == "3"); + + std::string getPerfDataStartType{"SELECT * FROM symbols where id="}; + getPerfDataStartType += hkFieldsRecords.at(35)["type"]; + getPerfDataStartType += ";"; + + std::vector> PerfDataStartTypeRecords{}; + + rc = sqlite3_exec(database, getPerfDataStartType.c_str(), selectCallbackUsingColNameAsKey, &PerfDataStartTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(PerfDataStartTypeRecords.size() == 1); + + std::string PerfDataStartType{PerfDataStartTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(35)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(35)["name"] == "PerfDataStart"); + REQUIRE(hkFieldsRecords.at(35)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, PerfDataStart))); + REQUIRE(hkFieldsRecords.at(35)["type"] == PerfDataStartType); + REQUIRE(hkFieldsRecords.at(35)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(35)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(35)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(35)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(35)["long_description"] == ""); + + std::string getPerfDataEndType{"SELECT * FROM symbols where id="}; + getPerfDataEndType += hkFieldsRecords.at(36)["type"]; + getPerfDataEndType += ";"; + + std::vector> PerfDataEndTypeRecords{}; + + rc = sqlite3_exec(database, getPerfDataEndType.c_str(), selectCallbackUsingColNameAsKey, &PerfDataEndTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(PerfDataEndTypeRecords.size() == 1); + + std::string PerfDataEndType{PerfDataEndTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(36)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(36)["name"] == "PerfDataEnd"); + REQUIRE(hkFieldsRecords.at(36)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, PerfDataEnd))); + REQUIRE(hkFieldsRecords.at(36)["type"] == PerfDataEndType); + REQUIRE(hkFieldsRecords.at(36)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(36)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(36)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(36)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(36)["long_description"] == ""); + + std::string getPerfDataCountType{"SELECT * FROM symbols where id="}; + getPerfDataCountType += hkFieldsRecords.at(37)["type"]; + getPerfDataCountType += ";"; + + std::vector> PerfDataCountTypeRecords{}; + + rc = sqlite3_exec(database, getPerfDataCountType.c_str(), selectCallbackUsingColNameAsKey, &PerfDataCountTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(PerfDataCountTypeRecords.size() == 1); + + std::string PerfDataCountType{PerfDataCountTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(37)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(37)["name"] == "PerfDataCount"); + REQUIRE(hkFieldsRecords.at(37)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, PerfDataCount))); + REQUIRE(hkFieldsRecords.at(37)["type"] == PerfDataCountType); + REQUIRE(hkFieldsRecords.at(37)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(37)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(37)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(37)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(37)["long_description"] == ""); + + std::string getPerfDataToWriteType{"SELECT * FROM symbols where id="}; + getPerfDataToWriteType += hkFieldsRecords.at(38)["type"]; + getPerfDataToWriteType += ";"; + + std::vector> PerfDataToWriteTypeRecords{}; + + rc = sqlite3_exec(database, getPerfDataToWriteType.c_str(), selectCallbackUsingColNameAsKey, &PerfDataToWriteTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(PerfDataToWriteTypeRecords.size() == 1); + + std::string PerfDataToWriteType{PerfDataToWriteTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(38)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(38)["name"] == "PerfDataToWrite"); + REQUIRE(hkFieldsRecords.at(38)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, PerfDataToWrite))); + REQUIRE(hkFieldsRecords.at(38)["type"] == PerfDataToWriteType); + REQUIRE(hkFieldsRecords.at(38)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(38)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(38)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(38)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(38)["long_description"] == ""); + + std::string getHeapBytesFreeType{"SELECT * FROM symbols where id="}; + getHeapBytesFreeType += hkFieldsRecords.at(39)["type"]; + getHeapBytesFreeType += ";"; + + std::vector> HeapBytesFreeTypeRecords{}; + + rc = sqlite3_exec(database, getHeapBytesFreeType.c_str(), selectCallbackUsingColNameAsKey, &HeapBytesFreeTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(HeapBytesFreeTypeRecords.size() == 1); + + std::string HeapBytesFreeType{HeapBytesFreeTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(39)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(39)["name"] == "HeapBytesFree"); + REQUIRE(hkFieldsRecords.at(39)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, HeapBytesFree))); + REQUIRE(hkFieldsRecords.at(39)["type"] == HeapBytesFreeType); + REQUIRE(hkFieldsRecords.at(39)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(39)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(39)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(39)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(39)["long_description"] == ""); + + std::string getHeapBlocksFreeType{"SELECT * FROM symbols where id="}; + getHeapBlocksFreeType += hkFieldsRecords.at(40)["type"]; + getHeapBlocksFreeType += ";"; + + std::vector> HeapBlocksFreeTypeRecords{}; + + rc = sqlite3_exec(database, getHeapBlocksFreeType.c_str(), selectCallbackUsingColNameAsKey, &HeapBlocksFreeTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(HeapBlocksFreeTypeRecords.size() == 1); + + std::string HeapBlocksFreeType{HeapBlocksFreeTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(40)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(40)["name"] == "HeapBlocksFree"); + REQUIRE(hkFieldsRecords.at(40)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, HeapBlocksFree))); + REQUIRE(hkFieldsRecords.at(40)["type"] == HeapBlocksFreeType); + REQUIRE(hkFieldsRecords.at(40)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(40)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(40)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(40)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(40)["long_description"] == ""); + + std::string getHeapMaxBlockSizeType{"SELECT * FROM symbols where id="}; + getHeapMaxBlockSizeType += hkFieldsRecords.at(41)["type"]; + getHeapMaxBlockSizeType += ";"; + + std::vector> HeapMaxBlockSizeTypeRecords{}; + + rc = sqlite3_exec(database, getHeapMaxBlockSizeType.c_str(), selectCallbackUsingColNameAsKey, &HeapMaxBlockSizeTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(HeapMaxBlockSizeTypeRecords.size() == 1); + + std::string HeapMaxBlockSizeType{HeapMaxBlockSizeTypeRecords.at(0)["id"]}; + + REQUIRE(hkFieldsRecords.at(41)["symbol"] == hkTargetSymbolId); + REQUIRE(hkFieldsRecords.at(41)["name"] == "HeapMaxBlockSize"); + REQUIRE(hkFieldsRecords.at(41)["byte_offset"] == std::to_string(offsetof(CFE_ES_HousekeepingTlm_Payload, HeapMaxBlockSize))); + REQUIRE(hkFieldsRecords.at(41)["type"] == HeapMaxBlockSizeType); + REQUIRE(hkFieldsRecords.at(41)["little_endian"] == little_endian); + REQUIRE(hkFieldsRecords.at(41)["bit_size"] == "0"); + REQUIRE(hkFieldsRecords.at(41)["bit_offset"] == "0"); + REQUIRE(hkFieldsRecords.at(41)["short_description"] == ""); + REQUIRE(hkFieldsRecords.at(41)["long_description"] == ""); + + REQUIRE(remove("./test_db.sqlite") == 0); + delete idc; +} + +TEST_CASE("Test 32-bit binary.", "[main_test#10]") +{ + /** + * 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_3}; + + idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); + REQUIRE(idc != nullptr); + logger.logInfo("IDataContainer was constructed successfully for unit test."); + + juicer.setIDC(idc); + juicer.setExtras(true); + + rc = juicer.parse(inputFile); + + REQUIRE((juicer.getDwarfVersion() == 4 || juicer.getDwarfVersion() == 5)); + + REQUIRE(rc == JUICER_OK); + + std::string getSquareStructQuery{"SELECT * FROM symbols WHERE name = \"Square\"; "}; + + /** + *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::string getAllEncodings{"SELECT * FROM encodings"}; + + std::vector> encodingsRecords{}; + + rc = sqlite3_exec(database, getAllEncodings.c_str(), selectCallbackUsingColNameAsKey, &encodingsRecords, &errorMessage); + + REQUIRE(rc == SQLITE_OK); + + REQUIRE(encodingsRecords.size() == 18); + + /** + * @brief encodingMap A map of row_id -> encoding. + * i.e {"1":"DW_ATE_address", "2":"DW_ATE_boolean", etc}. Useful for avoiding having to look up the encoding by foreign of a symbol + * every time. + */ + std::map encodingMap{}; + + for (auto encodingRecord : encodingsRecords) + { + encodingMap[encodingRecord["id"]] = encodingRecord["encoding"]; + } + + std::vector> squareRecords{}; + + rc = sqlite3_exec(database, getSquareStructQuery.c_str(), selectCallbackUsingColNameAsKey, &squareRecords, &errorMessage); + + REQUIRE(rc == SQLITE_OK); + REQUIRE(squareRecords.size() == 1); + + uint32_t numberOfColumns = 0; + + for (auto pair : squareRecords.at(0)) + { + numberOfColumns++; + } + + REQUIRE(numberOfColumns == 9); + + /** + * Check the correctness of Square struct. + */ + + REQUIRE(squareRecords.at(0)["name"] == "Square"); + REQUIRE(squareRecords.at(0)["byte_size"] == std::to_string(sizeof(Square))); + + REQUIRE(squareRecords.at(0)["target_symbol"] == "NULL"); + REQUIRE(squareRecords.at(0).at("encoding") == "NULL"); + REQUIRE(squareRecords.at(0)["short_description"] == ""); + REQUIRE(squareRecords.at(0)["long_description"] == ""); + + std::string square_id = squareRecords.at(0)["id"]; + + std::string square_artifact_id = squareRecords.at(0)["artifact"]; + + REQUIRE(!square_artifact_id.empty()); + + std::string getSquareArtifact{"SELECT * FROM artifacts WHERE id = "}; + + getSquareArtifact += square_artifact_id; + getSquareArtifact += ";"; + + std::vector> squareArtifactRecords{}; + + rc = sqlite3_exec(database, getSquareArtifact.c_str(), selectCallbackUsingColNameAsKey, &squareArtifactRecords, &errorMessage); + + REQUIRE(squareArtifactRecords.size() == 1); + + std::string path{}; + char resolvedPath[PATH_MAX]; + + realpath("../unit-test/test_file1.h", resolvedPath); + + path.clear(); + path.insert(0, resolvedPath); + + REQUIRE(squareArtifactRecords.at(0)["path"] == path); + + std::string expectedMD5Str = getmd5sumFromSystem(resolvedPath); + REQUIRE(expectedMD5Str == squareArtifactRecords.at(0)["md5"]); + + std::string getSquareFields{"SELECT * FROM fields WHERE symbol = "}; + + getSquareFields += square_id; + getSquareFields += ";"; + + std::vector> squareFieldsRecords{}; + + rc = sqlite3_exec(database, getSquareFields.c_str(), selectCallbackUsingColNameAsKey, &squareFieldsRecords, &errorMessage); + + REQUIRE(rc == SQLITE_OK); + REQUIRE(squareFieldsRecords.size() == 11); + + // // Enforce order of records by offset + std::sort(squareFieldsRecords.begin(), squareFieldsRecords.end(), [](std::map a, std::map b) + { return std::stoi(a["byte_offset"]) < std::stoi(b["byte_offset"]); }); + + std::string getWidthType{"SELECT * FROM symbols where id="}; + getWidthType += squareFieldsRecords.at(0)["type"]; + getWidthType += ";"; + + std::vector> widthTypeRecords{}; + + rc = sqlite3_exec(database, getWidthType.c_str(), selectCallbackUsingColNameAsKey, &widthTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(widthTypeRecords.size() == 1); + + std::string widthType{widthTypeRecords.at(0)["id"]}; + + REQUIRE(squareFieldsRecords.at(0)["symbol"] == squareRecords.at(0)["id"]); + REQUIRE(squareFieldsRecords.at(0)["name"] == "width"); + REQUIRE(squareFieldsRecords.at(0)["byte_offset"] == std::to_string(offsetof(Square, width))); + REQUIRE(squareFieldsRecords.at(0)["type"] == widthType); + REQUIRE(squareFieldsRecords.at(0)["little_endian"] == little_endian); + + std::string getStuffType{"SELECT * FROM symbols where id="}; + getStuffType += squareFieldsRecords.at(1)["type"]; + getStuffType += ";"; + + std::vector> stuffTypeRecords{}; + + rc = sqlite3_exec(database, getStuffType.c_str(), selectCallbackUsingColNameAsKey, &stuffTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(stuffTypeRecords.size() == 1); + + REQUIRE(stuffTypeRecords.at(0)["name"] == "uint16_t"); + REQUIRE(stuffTypeRecords.at(0)["byte_size"] == std::to_string(sizeof(uint16_t))); + + REQUIRE(encodingMap.at(followTargetSymbol(database, stuffTypeRecords.at(0)["target_symbol"]).at("encoding")) == "DW_ATE_unsigned"); + REQUIRE(stuffTypeRecords.at(0)["short_description"] == ""); + REQUIRE(stuffTypeRecords.at(0)["long_description"] == ""); + + std::string stuffType{stuffTypeRecords.at(0)["id"]}; + + REQUIRE(squareFieldsRecords.at(1)["name"] == "stuff"); + REQUIRE(squareFieldsRecords.at(1)["byte_offset"] == std::to_string(offsetof(Square, stuff))); + REQUIRE(squareFieldsRecords.at(1)["type"] == stuffType); + REQUIRE(squareFieldsRecords.at(1)["little_endian"] == little_endian); + + std::string getPadding1Type{"SELECT * FROM symbols where id="}; + getPadding1Type += squareFieldsRecords.at(2)["type"]; + getPadding1Type += ";"; + + std::vector> padding1TypeRecords{}; + + rc = sqlite3_exec(database, getPadding1Type.c_str(), selectCallbackUsingColNameAsKey, &padding1TypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(padding1TypeRecords.size() == 1); + + REQUIRE(padding1TypeRecords.at(0)["name"] == "uint16_t"); + REQUIRE(padding1TypeRecords.at(0)["byte_size"] == std::to_string(sizeof(uint16_t))); + + REQUIRE(encodingMap.at(followTargetSymbol(database, padding1TypeRecords.at(0)["target_symbol"]).at("encoding")) == "DW_ATE_unsigned"); + REQUIRE(padding1TypeRecords.at(0)["short_description"] == ""); + REQUIRE(padding1TypeRecords.at(0)["long_description"] == ""); + + std::string padding1Type{padding1TypeRecords.at(0)["id"]}; + + REQUIRE(squareFieldsRecords.at(2)["name"] == "padding1"); + REQUIRE(squareFieldsRecords.at(2)["byte_offset"] == std::to_string(offsetof(Square, padding1))); + REQUIRE(squareFieldsRecords.at(2)["type"] == padding1Type); + REQUIRE(squareFieldsRecords.at(2)["little_endian"] == little_endian); + + std::string getLengthType{"SELECT * FROM symbols where id="}; + getLengthType += squareFieldsRecords.at(3)["type"]; + getLengthType += ";"; + + std::vector> lengthTypeRecords{}; + + rc = sqlite3_exec(database, getLengthType.c_str(), selectCallbackUsingColNameAsKey, &lengthTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(lengthTypeRecords.size() == 1); + + REQUIRE(lengthTypeRecords.at(0)["name"] == "int32_t"); + REQUIRE(lengthTypeRecords.at(0)["byte_size"] == std::to_string(sizeof(int32_t))); + + REQUIRE(encodingMap.at(followTargetSymbol(database, lengthTypeRecords.at(0)["target_symbol"]).at("encoding")) == "DW_ATE_signed"); + REQUIRE(lengthTypeRecords.at(0)["short_description"] == ""); + REQUIRE(lengthTypeRecords.at(0)["long_description"] == ""); + + std::string lengthType{lengthTypeRecords.at(0)["id"]}; + + REQUIRE(squareFieldsRecords.at(3)["name"] == "length"); + REQUIRE(squareFieldsRecords.at(3)["byte_offset"] == std::to_string(offsetof(Square, length))); + REQUIRE(squareFieldsRecords.at(3)["type"] == lengthType); + REQUIRE(squareFieldsRecords.at(3)["little_endian"] == little_endian); + + std::string getMoreStuffType{"SELECT * FROM symbols where id="}; + getMoreStuffType += squareFieldsRecords.at(4)["type"]; + getMoreStuffType += ";"; + + std::vector> moreStuffTypeRecords{}; + + rc = sqlite3_exec(database, getMoreStuffType.c_str(), selectCallbackUsingColNameAsKey, &moreStuffTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(moreStuffTypeRecords.size() == 1); + + REQUIRE(moreStuffTypeRecords.at(0)["name"] == "uint16_t"); + REQUIRE(moreStuffTypeRecords.at(0)["byte_size"] == std::to_string(sizeof(uint16_t))); + + REQUIRE(encodingMap.at(followTargetSymbol(database, moreStuffTypeRecords.at(0)["target_symbol"]).at("encoding")) == "DW_ATE_unsigned"); + REQUIRE(moreStuffTypeRecords.at(0)["short_description"] == ""); + REQUIRE(moreStuffTypeRecords.at(0)["long_description"] == ""); + + std::string moreStuffType{moreStuffTypeRecords.at(0)["id"]}; + + REQUIRE(squareFieldsRecords.at(4)["name"] == "more_stuff"); + REQUIRE(squareFieldsRecords.at(4)["byte_offset"] == std::to_string(offsetof(Square, more_stuff))); + REQUIRE(squareFieldsRecords.at(4)["type"] == moreStuffType); + REQUIRE(squareFieldsRecords.at(4)["little_endian"] == little_endian); + + std::string getPadding2Type{"SELECT * FROM symbols where id="}; + getPadding2Type += squareFieldsRecords.at(5)["type"]; + getPadding2Type += ";"; + + std::vector> padding2TypeRecords{}; + + rc = sqlite3_exec(database, getPadding2Type.c_str(), selectCallbackUsingColNameAsKey, &padding2TypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(padding2TypeRecords.size() == 1); + + REQUIRE(padding2TypeRecords.at(0)["name"] == "uint16_t"); + REQUIRE(padding2TypeRecords.at(0)["byte_size"] == std::to_string(sizeof(uint16_t))); + + REQUIRE(encodingMap.at(followTargetSymbol(database, padding2TypeRecords.at(0)["target_symbol"]).at("encoding")) == "DW_ATE_unsigned"); + REQUIRE(padding2TypeRecords.at(0)["short_description"] == ""); + REQUIRE(padding2TypeRecords.at(0)["long_description"] == ""); + + std::string padding2Type{padding2TypeRecords.at(0)["id"]}; + + REQUIRE(squareFieldsRecords.at(5)["name"] == "padding2"); + REQUIRE(squareFieldsRecords.at(5)["byte_offset"] == std::to_string(offsetof(Square, padding2))); + REQUIRE(squareFieldsRecords.at(5)["type"] == padding2Type); + REQUIRE(squareFieldsRecords.at(5)["little_endian"] == little_endian); + + std::string getFloatingStuffType{"SELECT * FROM symbols where id="}; + getFloatingStuffType += squareFieldsRecords.at(6)["type"]; + getFloatingStuffType += ";"; + + std::vector> floatingStuffTypeRecords{}; + + rc = sqlite3_exec(database, getFloatingStuffType.c_str(), selectCallbackUsingColNameAsKey, &floatingStuffTypeRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(floatingStuffTypeRecords.size() == 1); + + REQUIRE(floatingStuffTypeRecords.at(0)["name"] == "float"); + REQUIRE(floatingStuffTypeRecords.at(0)["byte_size"] == std::to_string(sizeof(float))); + REQUIRE(floatingStuffTypeRecords.at(0)["target_symbol"] == "NULL"); + + REQUIRE(encodingMap.at(floatingStuffTypeRecords.at(0)["encoding"]) == "DW_ATE_float"); + REQUIRE(floatingStuffTypeRecords.at(0)["short_description"] == ""); + REQUIRE(floatingStuffTypeRecords.at(0)["long_description"] == ""); + + std::string floatingStuffType{floatingStuffTypeRecords.at(0)["id"]}; + + REQUIRE(squareFieldsRecords.at(6)["name"] == "floating_stuff"); + REQUIRE(squareFieldsRecords.at(6)["byte_offset"] == std::to_string(offsetof(Square, floating_stuff))); + REQUIRE(squareFieldsRecords.at(6)["type"] == floatingStuffType); + REQUIRE(squareFieldsRecords.at(6)["little_endian"] == little_endian); + + // Test matrix3D[2][4][4] + std::string getMatrix3DDimensionLists{"SELECT * FROM dimension_lists WHERE field_id="}; + getMatrix3DDimensionLists += squareFieldsRecords.at(7)["id"]; + getMatrix3DDimensionLists += ";"; + + std::vector> matrix3DDimensionListsRecords{}; + + rc = sqlite3_exec(database, getMatrix3DDimensionLists.c_str(), selectCallbackUsingColNameAsKey, &matrix3DDimensionListsRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(matrix3DDimensionListsRecords.size() == 3); + + // Enforce order of records by dim_order + std::sort(matrix3DDimensionListsRecords.begin(), matrix3DDimensionListsRecords.end(), + [](std::map a, std::map b) { return std::stoi(a["dim_order"]) < std::stoi(b["dim_order"]); }); + + REQUIRE(matrix3DDimensionListsRecords.at(0)["field_id"] == squareFieldsRecords.at(7)["id"]); + REQUIRE(matrix3DDimensionListsRecords.at(0)["dim_order"] == "0"); + REQUIRE(matrix3DDimensionListsRecords.at(0)["upper_bound"] == "1"); + + REQUIRE(matrix3DDimensionListsRecords.at(1)["field_id"] == squareFieldsRecords.at(7)["id"]); + REQUIRE(matrix3DDimensionListsRecords.at(1)["dim_order"] == "1"); + REQUIRE(matrix3DDimensionListsRecords.at(1)["upper_bound"] == "3"); + + REQUIRE(matrix3DDimensionListsRecords.at(2)["field_id"] == squareFieldsRecords.at(7)["id"]); + REQUIRE(matrix3DDimensionListsRecords.at(2)["dim_order"] == "2"); + REQUIRE(matrix3DDimensionListsRecords.at(2)["upper_bound"] == "3"); + + // Test matrix3D[2][4][4] + std::string getMatrix1DDimensionLists{"SELECT * FROM dimension_lists WHERE field_id="}; + getMatrix1DDimensionLists += squareFieldsRecords.at(8)["id"]; + getMatrix1DDimensionLists += ";"; + + std::vector> matrix1DDimensionListsRecords{}; + + rc = sqlite3_exec(database, getMatrix1DDimensionLists.c_str(), selectCallbackUsingColNameAsKey, &matrix1DDimensionListsRecords, &errorMessage); + REQUIRE(rc == SQLITE_OK); + REQUIRE(matrix1DDimensionListsRecords.size() == 1); + + // Enforce order of records by dim_order + std::sort(matrix1DDimensionListsRecords.begin(), matrix1DDimensionListsRecords.end(), + [](std::map a, std::map b) { return std::stoi(a["dim_order"]) < std::stoi(b["dim_order"]); }); + + REQUIRE(matrix1DDimensionListsRecords.at(0)["field_id"] == squareFieldsRecords.at(8)["id"]); + REQUIRE(matrix1DDimensionListsRecords.at(0)["dim_order"] == "0"); + REQUIRE(matrix1DDimensionListsRecords.at(0)["upper_bound"] == "1"); + + REQUIRE(remove("./test_db.sqlite") == 0); + delete idc; +} + +TEST_CASE("Write Elf File to database with verbosity set to DEBUG", "[main_test#11]") +{ + Juicer juicer; + IDataContainer* idc = 0; + Logger logger{LOGGER_VERBOSITY_DEBUG}; + + std::string inputFile{TEST_FILE_1}; + + idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); + REQUIRE(idc != nullptr); + logger.logInfo("IDataContainer was constructed successfully for unit test."); + + juicer.setIDC(idc); + juicer.parse(inputFile); + + REQUIRE((juicer.getDwarfVersion() == 4 || juicer.getDwarfVersion() == 5)); + + /** + *Clean up our database handle and objects in memory. + */ + ((SQLiteDB*)(idc))->close(); + delete idc; + REQUIRE(remove("./test_db.sqlite") == 0); +} +TEST_CASE("Write Elf File to database with verbosity set to WARNINGS", "[main_test#12]") +{ + Juicer juicer; + IDataContainer* idc = 0; + Logger logger{LOGGER_VERBOSITY_WARNINGS}; + + std::string inputFile{TEST_FILE_1}; + + idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); + REQUIRE(idc != nullptr); + logger.logInfo("IDataContainer was constructed successfully for unit test."); + + juicer.setIDC(idc); + juicer.parse(inputFile); + + REQUIRE((juicer.getDwarfVersion() == 4 || juicer.getDwarfVersion() == 5)); + + /** + *Clean up our database handle and objects in memory. + */ + ((SQLiteDB*)(idc))->close(); + delete idc; + REQUIRE(remove("./test_db.sqlite") == 0); +} +TEST_CASE("Write Elf File to database with verbosity set to ERRORS", "[main_test#13]") +{ + Juicer juicer; + IDataContainer* idc = 0; + Logger logger{LOGGER_VERBOSITY_ERRORS}; + + std::string inputFile{TEST_FILE_1}; + + idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); + REQUIRE(idc != nullptr); + logger.logInfo("IDataContainer was constructed successfully for unit test."); + + juicer.setIDC(idc); + juicer.parse(inputFile); + + REQUIRE((juicer.getDwarfVersion() == 4 || juicer.getDwarfVersion() == 5)); + + /** + *Clean up our database handle and objects in memory. + */ + ((SQLiteDB*)(idc))->close(); + delete idc; + REQUIRE(remove("./test_db.sqlite") == 0); +} +TEST_CASE("Write Elf File to database with verbosity set to SILENT", "[main_test#14]") +{ + Juicer juicer; + IDataContainer* idc = 0; + Logger logger{LOGGER_VERBOSITY_SILENT}; + + std::string inputFile{TEST_FILE_1}; + + idc = IDataContainer::Create(IDC_TYPE_SQLITE, "./test_db.sqlite"); + REQUIRE(idc != nullptr); + logger.logInfo("IDataContainer was constructed successfully for unit test."); + + juicer.setIDC(idc); + juicer.parse(inputFile); + + REQUIRE((juicer.getDwarfVersion() == 4 || juicer.getDwarfVersion() == 5)); + + /** + *Clean up our database handle and objects in memory. + */ + ((SQLiteDB*)(idc))->close(); + delete idc; + REQUIRE(remove("./test_db.sqlite") == 0); +} + +TEST_CASE("Write Elf File to database with IDC set to IDC_TYPE_CCDD.", "[main_test#15]") +{ + IDataContainer* idc = 0; + + idc = IDataContainer::Create(IDC_TYPE_CCDD, "./test_db.sqlite"); + REQUIRE(idc == nullptr); + + delete idc; +} + +TEST_CASE("Write Elf File to database with IDC set to an invalid value.", "[main_test#16]") +{ + IDataContainer* idc = 0; + + idc = IDataContainer::Create((IDataContainer_Type_t)100, "./test_db.sqlite"); + REQUIRE(idc == nullptr); + + delete idc; +} + +TEST_CASE("Test the correctness of define macros.", "[main_test#17]") +{ + /** + * 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_1}; + + 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); + + std::string getMacroQuery{"SELECT * FROM macros WHERE name = \"CFE_MISSION_ES_PERF_MAX_IDS\"; "}; + + /** + *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> macroRecords{}; + + rc = sqlite3_exec(database, getMacroQuery.c_str(), selectCallbackUsingColNameAsKey, ¯oRecords, &errorMessage); + + REQUIRE(rc == SQLITE_OK); + REQUIRE(macroRecords.size() == 1); + + uint32_t numberOfColumns = 0; + + for (auto pair : macroRecords.at(0)) + { + numberOfColumns++; + } + + REQUIRE(numberOfColumns == 7); + + REQUIRE(macroRecords.at(0).at("name") == "CFE_MISSION_ES_PERF_MAX_IDS"); + REQUIRE(macroRecords.at(0).at("value") == "128"); + + /** + * Check the correctness of macro. + */ + + REQUIRE(remove("./test_db.sqlite") == 0); + delete idc; +} + +TEST_CASE("Test the correctness of define macros across multiple groups.", "[main_test#18]") +{ + /** + * 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_4}; + + 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); + + // Group5 has macros "MAC4", "MAC5" + // Some more details about how this happens:https://lists.dwarfstd.org/pipermail/dwarf-discuss/2024-September/thread.html#2505 + juicer.setGroupNumber(5); + + rc = juicer.parse(inputFile); + + REQUIRE((juicer.getDwarfVersion() == 4 || juicer.getDwarfVersion() == 5)); + + REQUIRE(rc == JUICER_OK); + + std::string getMacroQuery{"SELECT * FROM macros; "}; + + /** + *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> macroRecords{}; + + rc = sqlite3_exec(database, getMacroQuery.c_str(), selectCallbackUsingColNameAsKey, ¯oRecords, &errorMessage); + + REQUIRE(rc == SQLITE_OK); + REQUIRE(macroRecords.size() == 5); + + uint32_t numberOfColumns = 0; + + for (auto pair : macroRecords.at(0)) + { + numberOfColumns++; + } + + REQUIRE(numberOfColumns == 7); + + REQUIRE(macroRecords.at(0).at("name") == "MAC1"); + REQUIRE(macroRecords.at(0).at("value") == "2"); + + REQUIRE(macroRecords.at(1).at("name") == "MAC2"); + REQUIRE(macroRecords.at(1).at("value") == "3"); + + REQUIRE(macroRecords.at(2).at("name") == "MAC3"); + REQUIRE(macroRecords.at(2).at("value") == "4"); + + REQUIRE(macroRecords.at(3).at("name") == "MAC4"); + REQUIRE(macroRecords.at(3).at("value") == ""); + + REQUIRE(macroRecords.at(4).at("name") == "MAC5"); + REQUIRE(macroRecords.at(4).at("value") == "1"); + + /** + * Check the correctness of macro. + */ + + REQUIRE(remove("./test_db.sqlite") == 0); + delete idc; +} + +TEST_CASE("Test the correctness of artifacts.", "[main_test#19]") +{ + /** + * 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_1}; + + 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 getArtifactQuery{"SELECT * FROM artifacts where path= \"/usr/include/x86_64-linux-gnu/bits/types.h\" ; "}; + + /** + *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> artiffactRecords{}; + + rc = sqlite3_exec(database, getArtifactQuery.c_str(), selectCallbackUsingColNameAsKey, &artiffactRecords, &errorMessage); + + REQUIRE(rc == SQLITE_OK); + REQUIRE(artiffactRecords.size() == 1); + + uint32_t numberOfColumns = 0; + + for (auto pair : artiffactRecords.at(0)) + { + numberOfColumns++; + } + + REQUIRE(numberOfColumns == 4); + + REQUIRE(artiffactRecords.at(0).find("id") != artiffactRecords.at(0).end()); + REQUIRE(artiffactRecords.at(0).find("elf") != artiffactRecords.at(0).end()); + REQUIRE(artiffactRecords.at(0).find("path") != artiffactRecords.at(0).end()); + REQUIRE(artiffactRecords.at(0).find("md5") != artiffactRecords.at(0).end()); + + REQUIRE(artiffactRecords.at(0).at("path") == "/usr/include/x86_64-linux-gnu/bits/types.h"); + + REQUIRE(remove("./test_db.sqlite") == 0); + delete idc; +} + +TEST_CASE("Test the correctness of bit fields.", "[main_test#20]") +{ + /** + * 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_1}; + + 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 getSymbolQuery{"SELECT * FROM symbols where name= \"S\" ; "}; + + /** + *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> symbolRecords{}; + + rc = sqlite3_exec(database, getSymbolQuery.c_str(), selectCallbackUsingColNameAsKey, &symbolRecords, &errorMessage); + + REQUIRE(rc == SQLITE_OK); + REQUIRE(symbolRecords.size() == 1); + + uint32_t numberOfColumns = 0; + + for (auto pair : symbolRecords.at(0)) + { + numberOfColumns++; + } + + REQUIRE(numberOfColumns == 9); + + REQUIRE(symbolRecords.at(0).at("byte_size") == std::to_string(sizeof(S))); + + /** + *Check the fields of the S struct. + */ + + std::string sId = symbolRecords.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/test_file1.cpp b/unit-test/test_file1.cpp index 6044a1f8..b2e5a8a5 100644 --- a/unit-test/test_file1.cpp +++ b/unit-test/test_file1.cpp @@ -8,59 +8,86 @@ *on our unit tests. */ +#ifdef __cplusplus +extern "C" { +#endif + #include "test_file1.h" -#include -#include -#include -#include -#include #include #include +#include +#include +#include + +Square sq = {}; +Circle ci = {}; + +Circle* ci_ptr = {}; + +__attribute__((used)) CFE_ES_HousekeepingTlm_t hk = {}; + +/* +** Local Structure Declarations +*/ +static __attribute__((used)) CFE_TBL_FileDef_t CFE_TBL_FileDef = { + /* Content format: ObjName[64], TblName[38], Desc[32], TgtFileName[20], ObjSize + ** ObjName - variable name of config table, e.g., CI_ConfigDefTbl[] + ** TblName - app's table name, e.g., CI.CONFIG_TBL, where CI is the same app name + ** used in cfe_es_startup.scr, and CI_defConfigTbl is the same table + ** name passed in to CFE_TBL_Register() + ** Desc - description of table in string format + ** TgtFileName[20] - table file name, compiled as .tbl file extension + ** ObjSize - size of the entire table + */ + + "ADC_ConfigTbl", "ADC.CONFIG_TBL", "ADC default config table", "adc_config.tbl", (sizeof(CFE_ES_HousekeepingTlm_t))}; -Square sq = {}; -Circle ci = {}; +int vector_x = 100; -int vector_x = 100; +unsigned int some_unsiged_int = 12; -unsigned int some_unsiged_int = 12; +int8_t precise_int8 = 110; -int8_t precise_int8 = 110; +int16_t precise_int16 = 110; -int16_t precise_int16 = 110; +int32_t precise_int32 = 110; -int32_t precise_int32 = 110; +int64_t precise_int64 = 110; -int64_t precise_int64 = 110; +uint8_t precise_unsigned_int8 = 112; -uint8_t precise_unsigned_int8 = 112; +uint16_t precise_unsigned_int16 = 112; -uint16_t precise_unsigned_int16 = 112; +uint32_t precise_unsigned_int32 = 112; -uint32_t precise_unsigned_int32 = 112; +uint64_t precise_unsigned_int64 = 112; -uint64_t precise_unsigned_int64 = 112; +char character = '2'; -char character = '2'; +int flat_array[] = {1, 2, 3, 4, 5, 6}; -int flat_array[] = {1,2,3,4,5,6}; +float some_float = 1.5; -float some_float = 1.5; +short some_short = 20; -short some_short = 20; +unsigned short some_signed_short = 14; -unsigned short some_signed_short = 14; +long a_long_value = 0; -long a_long_value = 0; +long long a_very_long_value = 0; -long long a_very_long_value = 0; +double some_double = 4.5; -double some_double = 4.5; +int vector_y = 30; -int vector_y = 30; +char alphabet[] = {'a', 'b', 'c'}; -char alphabet[] = {'a', 'b', 'c'}; +enum Color rainbow = RED; -enum Color rainbow = RED; +int another_array[] = {20, 21, 22, 34}; -int another_array[] = {20,21,22,34}; +S s_struct{}; +#ifdef __cplusplus +} +#endif diff --git a/unit-test/test_file1.h b/unit-test/test_file1.h index 3893d3ea..29052592 100644 --- a/unit-test/test_file1.h +++ b/unit-test/test_file1.h @@ -9,17 +9,145 @@ *on our unit tests. */ -#ifndef TEST_FILE_H_ -#define TEST_FILE_H_ +#define CFE_MISSION_ES_PERF_MAX_IDS 128 + #include "stdint.h" union Oject { - int32_t id; - char data[16]; + int32_t id; + char data[16]; }; +/*************************************************************************/ + +/** +** \cfeestlm Executive Services Housekeeping Packet +** +** struct taken from https://github.com/nasa/cFE/blob/fa5031f3f5db91b482e947f4dc08d9103019d48e/modules/es/config/default_cfe_es_msgstruct.h#L440 +**/ + +extern "C" { +typedef struct CFE_ES_HousekeepingTlm_Payload +{ + uint8_t CommandCounter; /**< \cfetlmmnemonic \ES_CMDPC + \brief The ES Application Command Counter */ + uint8_t CommandErrorCounter; /**< \cfetlmmnemonic \ES_CMDEC + \brief The ES Application Command Error Counter */ + + uint16_t CFECoreChecksum; /**< \cfetlmmnemonic \ES_CKSUM + \brief Checksum of cFE Core Code */ + uint8_t CFEMajorVersion; /**< \cfetlmmnemonic \ES_CFEMAJORVER + \brief Major Version Number of cFE */ + uint8_t CFEMinorVersion; /**< \cfetlmmnemonic \ES_CFEMINORVER + \brief Minor Version Number of cFE */ + uint8_t CFERevision; /**< \cfetlmmnemonic \ES_CFEREVISION + \brief Sub-Minor Version Number of cFE */ + uint8_t CFEMissionRevision; /**< \cfetlmmnemonic \ES_CFEMISSIONREV + \brief Mission Version Number of cFE */ + uint8_t OSALMajorVersion; /**< \cfetlmmnemonic \ES_OSMAJORVER + \brief OS Abstraction Layer Major Version Number */ + uint8_t OSALMinorVersion; /**< \cfetlmmnemonic \ES_OSMINORVER + \brief OS Abstraction Layer Minor Version Number */ + uint8_t OSALRevision; /**< \cfetlmmnemonic \ES_OSREVISION + \brief OS Abstraction Layer Revision Number */ + uint8_t OSALMissionRevision; /**< \cfetlmmnemonic \ES_OSMISSIONREV + \brief OS Abstraction Layer MissionRevision Number */ + + uint8_t PSPMajorVersion; /**< \cfetlmmnemonic \ES_PSPMAJORVER + \brief Platform Support Package Major Version Number */ + uint8_t PSPMinorVersion; /**< \cfetlmmnemonic \ES_PSPMINORVER + \brief Platform Support Package Minor Version Number */ + uint8_t PSPRevision; /**< \cfetlmmnemonic \ES_PSPREVISION + \brief Platform Support Package Revision Number */ + uint8_t PSPMissionRevision; /**< \cfetlmmnemonic \ES_PSPMISSIONREV + \brief Platform Support Package MissionRevision Number */ + uint32_t SysLogBytesUsed; /**< \cfetlmmnemonic \ES_SYSLOGBYTEUSED + \brief Total number of bytes used in system log */ + uint32_t SysLogSize; /**< \cfetlmmnemonic \ES_SYSLOGSIZE + \brief Total size of the system log */ + uint32_t SysLogEntries; /**< \cfetlmmnemonic \ES_SYSLOGENTRIES + \brief Number of entries in the system log */ + uint32_t SysLogMode; /**< \cfetlmmnemonic \ES_SYSLOGMODE + \brief Write/Overwrite Mode */ + + uint32_t ERLogIndex; /**< \cfetlmmnemonic \ES_ERLOGINDEX + \brief Current index of the ER Log (wraps around) */ + uint32_t ERLogEntries; /**< \cfetlmmnemonic \ES_ERLOGENTRIES + \brief Number of entries made in the ER Log since the power on */ + + uint32_t RegisteredCoreApps; /**< \cfetlmmnemonic \ES_REGCOREAPPS + \brief Number of Applications registered with ES */ + uint32_t RegisteredExternalApps; /**< \cfetlmmnemonic \ES_REGEXTAPPS + \brief Number of Applications registered with ES */ + uint32_t RegisteredTasks; /**< \cfetlmmnemonic \ES_REGTASKS + \brief Number of Tasks ( main AND child tasks ) registered with ES */ + uint32_t RegisteredLibs; /**< \cfetlmmnemonic \ES_REGLIBS + \brief Number of Libraries registered with ES */ + + uint32_t ResetType; /**< \cfetlmmnemonic \ES_RESETTYPE + \brief Reset type ( PROCESSOR or POWERON ) */ + uint32_t ResetSubtype; /**< \cfetlmmnemonic \ES_RESETSUBTYPE + \brief Reset Sub Type */ + uint32_t ProcessorResets; /**< \cfetlmmnemonic \ES_PROCRESETCNT + \brief Number of processor resets since last power on */ + uint32_t MaxProcessorResets; /**< \cfetlmmnemonic \ES_MAXPROCRESETS + \brief Max processor resets before a power on is done */ + uint32_t BootSource; /**< \cfetlmmnemonic \ES_BOOTSOURCE + \brief Boot source ( as provided from BSP ) */ + + uint32_t PerfState; /**< \cfetlmmnemonic \ES_PERFSTATE + \brief Current state of Performance Analyzer */ + uint32_t PerfMode; /**< \cfetlmmnemonic \ES_PERFMODE + \brief Current mode of Performance Analyzer */ + uint32_t PerfTriggerCount; /**< \cfetlmmnemonic \ES_PERFTRIGCNT + \brief Number of Times Performance Analyzer has Triggered */ + uint32_t PerfFilterMask[CFE_MISSION_ES_PERF_MAX_IDS / 32]; /**< \cfetlmmnemonic \ES_PERFFLTRMASK + \brief Current Setting of Performance Analyzer Filter Masks */ + uint32_t PerfTriggerMask[CFE_MISSION_ES_PERF_MAX_IDS / 32]; /**< \cfetlmmnemonic \ES_PERFTRIGMASK + \brief Current Setting of Performance Analyzer Trigger Masks */ + uint32_t PerfDataStart; /**< \cfetlmmnemonic \ES_PERFDATASTART + \brief Identifies First Stored Entry in Performance Analyzer Log */ + uint32_t PerfDataEnd; /**< \cfetlmmnemonic \ES_PERFDATAEND + \brief Identifies Last Stored Entry in Performance Analyzer Log */ + uint32_t PerfDataCount; /**< \cfetlmmnemonic \ES_PERFDATACNT + \brief Number of Entries Put Into the Performance Analyzer Log */ + uint32_t PerfDataToWrite; /**< \cfetlmmnemonic \ES_PERFDATA2WRITE + \brief Number of Performance Analyzer Log Entries Left to be Written to Log Dump File */ + uint32_t HeapBytesFree; /**< \cfetlmmnemonic \ES_HEAPBYTESFREE + \brief Number of free bytes remaining in the OS heap */ + uint32_t HeapBlocksFree; /**< \cfetlmmnemonic \ES_HEAPBLKSFREE + \brief Number of free blocks remaining in the OS heap */ + uint32_t HeapMaxBlockSize; /**< \cfetlmmnemonic \ES_HEAPMAXBLK + \brief Number of bytes in the largest free block */ +} CFE_ES_HousekeepingTlm_Payload_t; +} +/** + * \brief cFS telemetry header + * + * This provides the definition of CFE_MSG_TelemetryHeader_t + */ +struct CFE_MSG_TelemetryHeader +{ + uint8_t Msg; /**< \brief Base message */ + uint8_t Sec; /**< \brief Secondary header */ + uint8_t Spare[4]; /**< \brief Pad to avoid compiler padding if payload + requires 64 bit alignment */ +}; + +typedef struct CFE_MSG_TelemetryHeader CFE_MSG_TelemetryHeader_t; + +typedef struct CFE_MSG_TelemetryHeader CFE_MSG_TelemetryHeader_t3; + +typedef CFE_MSG_TelemetryHeader_t CFE_MSG_TelemetryHeader_t2; + +typedef struct CFE_ES_HousekeepingTlm +{ + CFE_MSG_TelemetryHeader_t2 TelemetryHeader; /**< \brief Telemetry header */ + CFE_MSG_TelemetryHeader_t3 TelemetryHeader2; /**< \brief Telemetry header */ + CFE_ES_HousekeepingTlm_Payload_t Payload; /**< \brief Telemetry payload */ +} CFE_ES_HousekeepingTlm_t; /** *The fields padding1 and padding2(as the name implies) are to prevent @@ -28,55 +156,65 @@ union Oject */ typedef struct { - int32_t width = 101; + int32_t width = 101; uint16_t stuff; uint16_t padding1; - int32_t length; + int32_t length; uint16_t more_stuff; uint16_t padding2; - float floating_stuff; - float matrix3D[2][4][4]; - float matrix1D[2]; -}Square; - + float floating_stuff; + float matrix3D[2][4][4]; + float matrix1D[2]; + uint8_t extra; +} Square; enum ModeSlot_t { - MODE_SLOT_NONE = -1, - MODE_SLOT_1 = 0, - MODE_SLOT_2 = 1, - MODE_SLOT_3 = 2, - MODE_SLOT_4 = 3, - MODE_SLOT_5 = 4, - MODE_SLOT_6 = 5, - MODE_SLOT_MAX = 6 -} ; + MODE_SLOT_NONE = -1, + MODE_SLOT_1 = 0, + MODE_SLOT_2 = 1, + MODE_SLOT_3 = 2, + MODE_SLOT_4 = 3, + MODE_SLOT_5 = 4, + MODE_SLOT_6 = 5, + MODE_SLOT_MAX = 6 +}; struct Circle { - float diameter = 7; - float radius; - int points[128]; + float diameter = 7; + float radius; + int points[128]; ModeSlot_t mode; - Oject o; + Oject union_object; }; enum Color { - RED, - BLUE, - YELLOW + RED, + BLUE, + YELLOW }; - -struct S { -uint8_t before; -int j:5; -int k:6; -int m:5; -uint8_t p; -int n:8; -uint8_t after; +struct S +{ + uint8_t before; + int j : 5; + int k : 6; + int m : 5; + uint8_t p; + int n : 8; + uint8_t after; }; -#endif /* TEST_FILE_H_ */ +#define CFE_TBL_FILDEF_MAX_NAME_LEN 64 +#define CFE_TBL_FILDEF_FS_HDR_LEN 64 +#define CFE_TBL_FILDEF_OS_FILE_LEN 64 +typedef struct +{ + char ObjectName[64]; /**< \brief Name of instantiated variable that contains desired table image */ + char TableName[CFE_TBL_FILDEF_MAX_NAME_LEN]; /**< \brief Name of Table as defined onboard */ + char Description[CFE_TBL_FILDEF_FS_HDR_LEN]; /**< \brief Description of table image that is included in cFE File Header */ + char TgtFilename[CFE_TBL_FILDEF_OS_FILE_LEN]; /**< \brief Default filename to be used for output of elf2cfetbl utility */ + int32_t ObjectSize; /**< \brief Size, in bytes, of instantiated object */ +} CFE_TBL_FileDef_t; diff --git a/unit-test/test_file2.cpp b/unit-test/test_file2.cpp index 208468b9..e68cdc7c 100644 --- a/unit-test/test_file2.cpp +++ b/unit-test/test_file2.cpp @@ -1,56 +1,54 @@ -#include "test_file1.h" - -#include -#include -#include -#include -#include #include #include +#include +#include +#include + +#include "test_file1.h" -Square sq_2 = {}; -Circle ci_2 = {}; +Square sq_2 = {}; +Circle ci_2 = {}; -int vector_x_2 = 100; +int vector_x_2 = 100; -unsigned int some_unsiged_int_2 = 12; +unsigned int some_unsiged_int_2 = 12; -int8_t precise_int8_2 = 110; +int8_t precise_int8_2 = 110; -int16_t precise_int16_2 = 110; +int16_t precise_int16_2 = 110; -int32_t precise_int32_2 = 110; +int32_t precise_int32_2 = 110; -int64_t precise_int64_2 = 110; +int64_t precise_int64_2 = 110; -uint8_t precise_unsigned_int8_2 = 112; +uint8_t precise_unsigned_int8_2 = 112; -uint16_t precise_unsigned_int16_2 = 112; +uint16_t precise_unsigned_int16_2 = 112; -uint32_t precise_unsigned_int32_2 = 112; +uint32_t precise_unsigned_int32_2 = 112; -uint64_t precise_unsigned_int64_2 = 112; +uint64_t precise_unsigned_int64_2 = 112; -char character_2 = '2'; +char character_2 = '2'; -int flat_array_2[] = {1,2,3,4,5,6}; +int flat_array_2[] = {1, 2, 3, 4, 5, 6}; -float some_float_2 = 1.5; +float some_float_2 = 1.5; -short some_short_2 = 20; +short some_short_2 = 20; -unsigned short some_signed_short_2 = 14; +unsigned short some_signed_short_2 = 14; -long a_long_value_2 = 0; +long a_long_value_2 = 0; -long long a_very_long_value_2 = 0; +long long a_very_long_value_2 = 0; -double some_double_2 = 4.5; +double some_double_2 = 4.5; -int vector_y_2 = 30; +int vector_y_2 = 30; -char alphabet_2[] = {'a', 'b', 'c'}; +char alphabet_2[] = {'a', 'b', 'c'}; -enum Color rainbow_2 = RED; +enum Color rainbow_2 = RED; -int another_array_2[] = {20,21,22,34}; +int another_array_2[] = {20, 21, 22, 34}; diff --git a/unit-test/test_file2.h b/unit-test/test_file2.h index 34f80618..becd0317 100644 --- a/unit-test/test_file2.h +++ b/unit-test/test_file2.h @@ -8,8 +8,6 @@ #ifndef UNIT_TEST_TEST_FILE2_H_ #define UNIT_TEST_TEST_FILE2_H_ - #include "test_file1.h" - #endif /* UNIT_TEST_TEST_FILE2_H_ */