目录

  • 引言
  • parse_elf_jsonc.c
  • compare_elf_cJSON.cpp

引言

前段时间接触到了跟abi(注意不是api)相关的知识,简单的了解了一下elf文件格式并写了两个小样例。

具体的步骤为:

  • 修改readelf命令源码,增加其对h、S、l参数的json输出(修改后的代码过长就不放了)。
  • 可以不修改json源码,我用linux平台下的json-c写了一个自己的样例。
  • 对比获得的json文件,这里我用cJSON写了一个针对改后readelf的简单对比。

说实话对这方面兴趣真不大,发这篇博客当作一个因为个人原因可能即将烂尾的工程的纪念吧。

本篇博客代码和json文件下载:我的github仓库
elf文件格式简介:请参考《程序员的自我修养》第三章 目标文件里有什么
readelf命令简介:readelf (GNU Binary Utilities)
readelf命令源码:binutils/readelf.c
json文档:JSON中国 | JSON中文网

parse_elf_jsonc.c

#include <stdio.h>
#include <elf.h>
#include <fcntl.h>#include <unistd.h>
#include <stddef.h>
#include "json-c/json.h"#define my_err(format)      { \fprintf(stderr, "(File:%s, Line:%d) ", __FILE__, __LINE__); \perror(format); \exit(1); \} \
void read_file_header(int fd, struct json_object *elf_json_object) {if (lseek(fd, 0, SEEK_SET) == -1)my_err("lseek error");Elf64_Ehdr file_header;if (read(fd, (void*)&file_header, sizeof(file_header)) == -1)my_err("read error");struct json_object *file_header_json_obeject = json_object_new_object();unsigned char magic_string[17] = {0};for (int i = 0; i < 16; i++)magic_string[i] = file_header.e_ident[i] + '0';json_object_object_add(file_header_json_obeject, "Magic", json_object_new_string(magic_string));json_object_object_add(file_header_json_obeject, "Type", json_object_new_int64(file_header.e_type));json_object_object_add(file_header_json_obeject, "Machine", json_object_new_int64(file_header.e_machine));json_object_object_add(file_header_json_obeject, "Version", json_object_new_int64(file_header.e_version));json_object_object_add(file_header_json_obeject, "Entry point address", json_object_new_int64(file_header.e_entry));json_object_object_add(file_header_json_obeject, "Start of program headers", json_object_new_int64(file_header.e_phoff));json_object_object_add(file_header_json_obeject, "Start of section headers", json_object_new_int64(file_header.e_shoff));json_object_object_add(file_header_json_obeject, "Flags", json_object_new_int64(file_header.e_flags));json_object_object_add(file_header_json_obeject, "Size of this header", json_object_new_int64(file_header.e_ehsize));json_object_object_add(file_header_json_obeject, "Size of program headers", json_object_new_int64(file_header.e_phentsize));json_object_object_add(file_header_json_obeject, "Number of program headers", json_object_new_int64(file_header.e_phnum));json_object_object_add(file_header_json_obeject, "Size of section header", json_object_new_int64(file_header.e_shentsize));json_object_object_add(file_header_json_obeject, "Number of section headers", json_object_new_int64(file_header.e_shnum));json_object_object_add(file_header_json_obeject, "Section header string table index", json_object_new_int64(file_header.e_shstrndx));json_object_object_add(elf_json_object, "File Header", file_header_json_obeject);
}void read_program_header(int fd, struct json_object *elf_json_object) {if (lseek(fd, offsetof(Elf64_Ehdr, e_phoff), SEEK_SET) == -1)my_err("lseek error");Elf64_Off e_phoff;if (read(fd, (void*)&e_phoff, sizeof(e_phoff)) == -1)my_err("read error");if (lseek(fd, offsetof(Elf64_Ehdr, e_phnum), SEEK_SET) == -1)my_err("lseek error");Elf64_Half e_phnum;if (read(fd, (void*)&e_phnum, sizeof(e_phnum)) == -1)my_err("read error");if (lseek(fd, e_phoff, SEEK_SET) == -1)my_err("lseek error");Elf64_Phdr program_headers[e_phnum];struct json_object *program_header_json_array = json_object_new_array();for (Elf64_Half i = 0; i < e_phnum; i++) {if (read(fd, (void *)&(program_headers[i]), sizeof(program_headers[i])) == -1)my_err("read error");struct json_object *program_header_json_array_i = json_object_new_object();json_object_object_add(program_header_json_array_i, "Type", json_object_new_int64(program_headers[i].p_type));json_object_object_add(program_header_json_array_i, "Offset", json_object_new_int64(program_headers[i].p_offset));json_object_object_add(program_header_json_array_i, "VirtAddr", json_object_new_int64(program_headers[i].p_vaddr));json_object_object_add(program_header_json_array_i, "PhysAddr", json_object_new_int64(program_headers[i].p_paddr));json_object_object_add(program_header_json_array_i, "FileSiz", json_object_new_int64(program_headers[i].p_filesz));json_object_object_add(program_header_json_array_i, "MemSiz", json_object_new_int64(program_headers[i].p_memsz));json_object_object_add(program_header_json_array_i, "Flg", json_object_new_int64(program_headers[i].p_flags));json_object_object_add(program_header_json_array_i, "Align", json_object_new_int64(program_headers[i].p_align));json_object_array_add(program_header_json_array, program_header_json_array_i);}json_object_object_add(elf_json_object, "Program Headers", program_header_json_array);
}void read_section_header(int fd, struct json_object *elf_json_object) {if (lseek(fd, offsetof(Elf64_Ehdr, e_shoff), SEEK_SET) == -1)my_err("lseek error");Elf64_Off e_shoff;if (read(fd, (void*)&e_shoff, sizeof(e_shoff)) == -1)my_err("read error");if (lseek(fd, offsetof(Elf64_Ehdr, e_shnum), SEEK_SET) == -1)my_err("lseek error");Elf64_Half e_shnum;if (read(fd, (void*)&e_shnum, sizeof(e_shnum)) == -1)my_err("read error");if (lseek(fd, e_shoff, SEEK_SET) == -1)my_err("lseek error");Elf64_Shdr section_headers[e_shnum];struct json_object *section_header_json_array = json_object_new_array();for (Elf64_Half i = 0; i < e_shnum; i++) {if (read(fd, (void *)&(section_headers[i]), sizeof(section_headers[i])) == -1)my_err("read error");struct json_object *section_header_json_array_i = json_object_new_object();json_object_object_add(section_header_json_array_i, "Name", json_object_new_int64(section_headers[i].sh_name));json_object_object_add(section_header_json_array_i, "Type", json_object_new_int64(section_headers[i].sh_type));json_object_object_add(section_header_json_array_i, "Addr", json_object_new_int64(section_headers[i].sh_addr));json_object_object_add(section_header_json_array_i, "Off", json_object_new_int64(section_headers[i].sh_offset));json_object_object_add(section_header_json_array_i, "Size", json_object_new_int64(section_headers[i].sh_size));json_object_object_add(section_header_json_array_i, "ES", json_object_new_int64(section_headers[i].sh_entsize));json_object_object_add(section_header_json_array_i, "Flg", json_object_new_int64(section_headers[i].sh_flags));json_object_object_add(section_header_json_array_i, "Lk", json_object_new_int64(section_headers[i].sh_link));json_object_object_add(section_header_json_array_i, "Inf", json_object_new_int64(section_headers[i].sh_info));json_object_object_add(section_header_json_array_i, "Al", json_object_new_int64(section_headers[i].sh_addralign));json_object_array_add(section_header_json_array, section_header_json_array_i);}json_object_object_add(elf_json_object, "Program Headers", section_header_json_array);
}int main(int argc, char **argv) {if (argc != 2) {printf("Usage : %s <filename>\n", argv[0]);return -1;}int fd = open(argv[1], O_RDONLY);
//  int fd = open("/home/nigo/桌面/try", O_RDONLY);if (fd == -1)my_err("open error");struct json_object *elf_json_object = json_object_new_object();read_file_header(fd, elf_json_object);read_program_header(fd, elf_json_object);read_section_header(fd, elf_json_object);printf("%s\n", json_object_to_json_string(elf_json_object));json_object_put(elf_json_object);if (close(fd) == -1)my_err("close error");return 0;
}

compare_elf_cJSON.cpp

// c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <cjson/cJSON.h>
#include <sys/stat.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
// cpp
#include <map>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>using namespace std;#define my_err(format)      { \fprintf(stderr, "(File:%s, Line:%d) ", __FILE__, __LINE__); \perror(format); \exit(1); \} \

enum move_type {move_none,move_down,move_right,move_diagonal
};map<move_type, const char*> color = {{move_down, "\033[32m"},{move_right, "\033[31m"},{move_diagonal, "\033[39m"},{move_none, "\033[0m"}
};class Point {friend move_type compare(const Point &prev_point, const Point &point);public:Point(int x, int y) {this->x = x;this->y = y;}bool operator==(const Point &point) const {return this->x == point.x && this->y == point.y;}bool operator!=(const Point &point) const {return this->x != point.x || this->y != point.y;}//  move_type operator>(const Point &point) {//  if (this->x == point.x && this->y + 1 == point.y) {//    return move_down;
//  } else if (this->y == point.y && this->x + 1 == point.x) {//    return move_right;
//  } else if (this->x + 1 == point.x && this->y + 1 == point.y) {//    return move_diagonal;
//  }
//  return move_none;
//  }public:int x = 0;int y = 0;
};// compare previous point and point
move_type compare(const Point &prev_point, const Point &point) {if (prev_point.x == point.x && prev_point.y + 1 == point.y) {return move_down;} else if (prev_point.y == point.y && prev_point.x + 1 == point.x) {return move_right;} else if (prev_point.x + 1 == point.x && prev_point.y + 1 == point.y) {return move_diagonal;}return move_none;
}// myers' diff algorithm:
// T1 and T2 should overload operator[] and size
// for example, T1 and T2 can be
// string to compare character
// or vector<T> to compare T
template<typename T1, typename T2>
void myers_diff(const T1 &lhs, const T2 &rhs) {int N = lhs.size();int M = rhs.size();// map to save v of every dvector<map<int, int>> res_v;// map to save x by k// k -> xmap<int, int> v;// base point : (0,-1)v[1] = 0;bool go_ahead = true;// d: step(excludes move of diagonal)// k: x - yfor (int d = 0; d <= N + M && go_ahead; d++) {for (int k = -d; k <= d; k = k + 2) {// delete is preferred// so move right is preferred// so bigger x is preferredbool down = (k == -d || (k != d && v[k - 1] < v[k + 1]));int k_prev = down ? k + 1 : k - 1;// start pointint x_start = v[k_prev];int y_start = x_start - k_prev;// temp(mid) pointint x_tmp = down ? x_start : x_start + 1;int y_tmp = x_tmp - k;// end pointint x_end = x_tmp;int y_end = y_tmp;// move along the diagonalwhile (x_end < N && y_end < M && lhs[x_end] == rhs[y_end]) {++x_end;++y_end;}v[k] = x_end;// the result is foundif (x_end >= N && y_end >= M) {go_ahead = false;break;}}// store the resultres_v.push_back(v);}// the fallbackvector<Point> path;Point point(lhs.size(), rhs.size());path.push_back(point);for (int d = res_v.size() - 1; point.x > 0 || point.y > 0; --d) {auto X = res_v[d];int k = point.x - point.y;int x_end = X[k];int y_end = point.x - k;// whether move along the diagonalwhile (x_end > 0 && y_end > 0 && x_end <= N && y_end <= M && lhs[x_end - 1] == rhs[y_end - 1]) {--x_end;--y_end;path.push_back(Point(x_end, y_end));}bool down = (k == -d || (k != d && X[k - 1] < X[k + 1]));int k_prev = down ? k + 1 : k - 1;int x_start = X[k_prev];int y_start = x_start - k_prev;path.push_back(Point(x_start, y_start));point.x = x_start;point.y = y_start;}// pop (0,-1)path.pop_back();// compare and printif (path.size() >= 2) {int size = path.size();for (int i = size - 2; i >= 0; --i) {Point prev_point = path[i + 1];move_type type = compare(prev_point, path[i]);switch (type) {case move_right: {cout << color[move_right] << "-" << lhs[prev_point.x] << endl;break;}case move_down: {cout << color[move_down] << "+" << rhs[prev_point.y] << endl;break;}case move_diagonal: {cout << color[move_diagonal] << "=" << lhs[prev_point.x] << endl;break;}}}}
}const int completed_option_nums = 2;
const double double_min_interval = 1e-6;long int diff_item_num = 0, same_item_num = 0,added_item_num = 0, deleted_item_num = 0;// split std::string by sep
// then return a vector<string> to store the result
vector<string> split_string(const string &str, const string &sep) {vector<string> res;string temp_s = str + sep;size_t pos = temp_s.find(sep);size_t size = temp_s.size();while (pos != string::npos) {// escape empty string(when sep is in the end)if (pos == 0)break;string s = temp_s.substr(0, pos);res.push_back(s);temp_s = temp_s.substr(pos + 1, size);pos = temp_s.find(sep);}return res;
}// parse from a filename to a json object
struct cJSON *cJSON_ParseFilename(const char *filename) {int fd = open(filename, O_RDONLY);if (fd == -1) my_err("open error");// obtain file sizestruct stat file_stat;if (fstat(fd, &file_stat) == -1) my_err("fstat error");__off_t size = file_stat.st_size;// read file by sizechar read_buf[size + 1];read(fd, (void *)read_buf, size);read_buf[size] = '\0';if (close(fd) == -1) my_err("close error");return cJSON_Parse(read_buf);
}// judge buf whether is number key
int is_number_key(const char *buf) {// number Key won't be printed// atoi return 0 when error happens or string is "0"if ((atoi(buf) != 0) && (!(*buf == '0' && (buf[1] == '\0'))))return 0;return 1;
}// compare normal cJSON Object and print
int cJSON_ComparePrintNormal(const struct cJSON *object1, const struct cJSON *object2, const char *dst_str) {const struct cJSON *json1, *json2;json1 = cJSON_GetObjectItem(object1, dst_str);json2 = cJSON_GetObjectItem(object2, dst_str);// avoid null cJSON objectif ((!json1) || (!json2))return -1;// classify and compareif (cJSON_IsString(json1) && cJSON_IsString(json2)) {// for cJSON String Objectconst char *str1, *str2;str1 = cJSON_GetStringValue(json1);str2 = cJSON_GetStringValue(json2);if (strcmp(str1, str2) != 0) {diff_item_num++;if (is_number_key(dst_str))printf("%s : \n", dst_str);cout << color[move_right] << "-" << str1 << endl << color[move_none];cout << color[move_down] << "+" << str2 << endl << color[move_none];} else {same_item_num++;}} else if (cJSON_IsNumber(json1) && cJSON_IsNumber(json2)) {// for cJSON Number objectdouble d1, d2;d1 = cJSON_GetNumberValue(json1);d2 = cJSON_GetNumberValue(json2);if (fabs(d1 - d2) > double_min_interval) {diff_item_num++;if (is_number_key(dst_str))printf("%s : \n", dst_str);printf("%s-%.0lf\n%s+%.0lf\n%s",color[move_right], d1, color[move_down], d2, color[move_none]);} else {same_item_num++;}} else if (cJSON_IsObject(json1) && cJSON_IsObject(json2)) {// for cJSON Object like "Version":      {//                         "0":    1,//                         "1":    "(current)"//                 },char nk_buf[11];    // number key buffer (0, 1, ...)// INT_MAX is 2147483647sprintf(nk_buf, "%d", 0);while (cJSON_ComparePrintNormal(json1, json2, nk_buf) != -1) {// 0 to 1 to ...int nk = atoi(nk_buf);sprintf(nk_buf, "%d", ++nk);}} else {printf("%s\n", dst_str);my_err("cJSON_ComparePrintNormal error");}return 0;
}// compare option h then output
void compare_option_h(const char *filename1, const char *filename2) {struct cJSON *object1 = cJSON_ParseFilename(filename1);struct cJSON *object2 = cJSON_ParseFilename(filename2);struct cJSON *temp1_cJSON, *temp2_cJSON;temp1_cJSON = cJSON_GetObjectItem(object1, "ELF Header");temp2_cJSON = cJSON_GetObjectItem(object2, "ELF Header");printf("<option h> : \n");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "OS/ABI");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "ABI Version");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Type");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Machine");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Version");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Entry point address");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Start of program headers");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Start of section headers");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Size of this header");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Size of program headers");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Number of program headers");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Size of section headers");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Number of section headers");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Section header string table index");// just delete root cJSON object// otherwise cause double-freecJSON_Delete(object1);cJSON_Delete(object2);
}// compare option S then output
void compare_option_S(const char *filename1, const char *filename2) {struct cJSON *object1 = cJSON_ParseFilename(filename1);struct cJSON *object2 = cJSON_ParseFilename(filename2);struct cJSON *temp1_cJSON, *temp2_cJSON;temp1_cJSON = cJSON_GetObjectItem(object1, "Section Headers");temp2_cJSON = cJSON_GetObjectItem(object2, "Section Headers");printf("<option S> \n");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "elf_header.e_shnum");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "elf_header.e_shoff");// compare Section Headersstruct cJSON *temp1_array_cJSON, *temp2_array_cJSON;temp1_array_cJSON = cJSON_GetObjectItem(temp1_cJSON, "Section Headers");temp2_array_cJSON = cJSON_GetObjectItem(temp2_cJSON, "Section Headers");printf("Section Headers : \n");int array_size = cJSON_GetArraySize(temp1_array_cJSON);if (array_size != cJSON_GetArraySize(temp2_array_cJSON)) my_err("cJSON_GetArraySize error");for (int i = 0; i < array_size; ++i) {temp1_cJSON = cJSON_GetArrayItem(temp1_array_cJSON, i);temp2_cJSON = cJSON_GetArrayItem(temp2_array_cJSON, i);cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Name");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Type");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Off");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Size");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "ES");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Flg");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Lk");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Inf");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Al");}cJSON_Delete(object1);cJSON_Delete(object2);
}// compare option l then output
void compare_option_l(const char *filename1, const char *filename2) {struct cJSON *object1 = cJSON_ParseFilename(filename1);struct cJSON *object2 = cJSON_ParseFilename(filename2);struct cJSON *temp1_cJSON, *temp2_cJSON;temp1_cJSON = cJSON_GetObjectItem(object1, "Program Header");temp2_cJSON = cJSON_GetObjectItem(object2, "Program Header");printf("<option l> : \n");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Elf file type\"");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Entry point");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "elf_header.e_phnum");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "starting at offset");// compare Section Headersstruct cJSON *temp1_array_cJSON, *temp2_array_cJSON;temp1_array_cJSON = cJSON_GetObjectItem(temp1_cJSON, "Program Headers");temp2_array_cJSON = cJSON_GetObjectItem(temp2_cJSON, "Program Headers");printf("Program Headers : \n");int array_size = cJSON_GetArraySize(temp1_array_cJSON);if (array_size != cJSON_GetArraySize(temp2_array_cJSON)) my_err("cJSON_GetArraySize error");for (int i = 0; i < array_size; ++i) {temp1_cJSON = cJSON_GetArrayItem(temp1_array_cJSON, i);temp2_cJSON = cJSON_GetArrayItem(temp2_array_cJSON, i);cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Type");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Offset");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "VirtAddr");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "PhysAddr");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "FileSiz");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "MemSiz");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Flg");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "Align");}cJSON_Delete(object1);cJSON_Delete(object2);
}// compare option r then output
void compare_option_r(const char *filename1, const char *filename2) {struct cJSON *object1 = cJSON_ParseFilename(filename1);struct cJSON *object2 = cJSON_ParseFilename(filename2);struct cJSON *temp1_cJSON, *temp2_cJSON;temp1_cJSON = cJSON_GetObjectItem(object1, "Relocation");temp2_cJSON = cJSON_GetObjectItem(object2, "Relocation");printf("<option r> : \n");// compare .rel.dynstruct cJSON *temp1_array_cJSON, *temp2_array_cJSON;temp1_array_cJSON = cJSON_GetObjectItem(temp1_cJSON, ".rel.dyn");temp2_array_cJSON = cJSON_GetObjectItem(temp2_cJSON, ".rel.dyn");printf(".rel.dyn : \n");int array_size = cJSON_GetArraySize(temp1_array_cJSON);if (array_size != cJSON_GetArraySize(temp2_array_cJSON)) my_err("cJSON_GetArraySize error");for (int i = 0; i < array_size; ++i) {temp1_cJSON = cJSON_GetArrayItem(temp1_array_cJSON, i);temp2_cJSON = cJSON_GetArrayItem(temp2_array_cJSON, i);cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "offset");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "info");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "type");cJSON_ComparePrintNormal(temp1_cJSON, temp2_cJSON, "sym->value");}cJSON_Delete(object1);cJSON_Delete(object2);
}// print section cJSON object like
// {"section_name":{"0":"address","1":"value"}
void cJSON_PrintSection(struct cJSON *section_object, const char *section_name, move_type type) {printf("%s", color[type]);if (type == move_right) {printf("-");} else if (type == move_down) {printf("+");}printf("%s : \n", section_name);auto temp_cJSON = cJSON_GetObjectItem(section_object, section_name);printf("address : %s\n", cJSON_GetObjectItem(temp_cJSON, "0")->valuestring);auto vec_s = split_string(cJSON_GetObjectItem(temp_cJSON, "1")->valuestring, " ");int i;for (i = 0; i < vec_s.size(); i++) {if (i == 4) {i = 0;printf("\n");}cout << vec_s[i] << " ";}if (i != 4)printf("\n");printf("%s", color[move_none]);
}// compare section cJSON object like
// {"section_name":{"0":"address","1":"value"}
// return 0 when same, 1 when different
int cJSON_ComparePrintSection(const struct cJSON *object1, const struct cJSON *object2, const char *dst_str) {int is_diff = 0;int is_sname_print = 0;const struct cJSON *json1, *json2;json1 = cJSON_GetObjectItem(object1, dst_str);json2 = cJSON_GetObjectItem(object2, dst_str);auto temp1_cJSON = cJSON_GetObjectItem(json1, "0");auto temp2_cJSON = cJSON_GetObjectItem(json2, "0");auto temp1_str = cJSON_GetStringValue(temp1_cJSON);auto temp2_str = cJSON_GetStringValue(temp2_cJSON);if (strcmp(temp1_str, temp2_str)) {is_diff = is_sname_print = 1;printf("%s : \n", dst_str);printf("address : \n");printf("%s-%s\n%s",color[move_right], temp1_str, color[move_none]);printf("%s+%s\n%s",color[move_down], temp2_str, color[move_none]);}temp1_cJSON = cJSON_GetObjectItem(json1, "1");temp2_cJSON = cJSON_GetObjectItem(json2, "1");temp1_str = cJSON_GetStringValue(temp1_cJSON);temp2_str = cJSON_GetStringValue(temp2_cJSON);if (strcmp(temp1_str, temp2_str)) {if (!is_sname_print) {is_sname_print = 1;printf("%s : \n", dst_str);}printf("value : \n");// myers' diffmyers_diff(split_string(temp1_str, " "), split_string(temp2_str, " "));}return is_diff;
}// compare option x(improved) then output
// show all section headers
void compare_option_x_i(const char *filename1, const char *filename2) {struct cJSON *object1 = cJSON_ParseFilename(filename1);struct cJSON *object2 = cJSON_ParseFilename(filename2);printf("<option x(improved)> : \n");// compare Hex dump of sectionstruct cJSON *temp1_array_cJSON, *temp2_array_cJSON;temp1_array_cJSON = cJSON_GetObjectItem(object1, "Hex dump of section");temp2_array_cJSON = cJSON_GetObjectItem(object2, "Hex dump of section");printf("Hex dump of section : \n");int array1_size = cJSON_GetArraySize(temp1_array_cJSON);int array2_size = cJSON_GetArraySize(temp2_array_cJSON);struct cJSON *temp1_cJSON, *temp2_cJSON;const char *section_name;// the same string(const char*) may have different address// so the key must be std::stringmap<string, struct cJSON *> s_map;// create a map of sectionsfor (int i = 0; i < array1_size; ++i) {temp1_cJSON = cJSON_GetArrayItem(temp1_array_cJSON, i);section_name = temp1_cJSON->child->string;s_map[section_name] = temp1_cJSON;}// compare and update related variablesfor (int i = 0; i < array2_size; ++i) {temp2_cJSON = cJSON_GetArrayItem(temp2_array_cJSON, i);section_name = temp2_cJSON->child->string;if (s_map.find(section_name) != s_map.end()) {// there are same sections in two file// compare themint is_diff = cJSON_ComparePrintSection(s_map[section_name], temp2_cJSON, section_name);// after comparison, erase elementif (is_diff)diff_item_num++;elsesame_item_num++;s_map.erase(section_name);} else {// otherwise output individuallychar *temp_str;cJSON_PrintSection(temp2_cJSON, section_name, move_down);added_item_num++;}}// updating deleted_item_num must be heredeleted_item_num += s_map.size();for (auto s : s_map) {cJSON_PrintSection(s.second, s.first.c_str(), move_right);
//  printf("%s-%s\n%s",
//         color[move_right], cJSON_PrintUnformatted(s.second), color[move_none]);}cJSON_Delete(object1);cJSON_Delete(object2);
}int main(int argc, char *argv[]) {//  if (argc != completed_option_nums * 2 + 1) {//  printf("Usage : %s <filename-h-1> <filename-h-2> "
//         "<filename-S-1> <filename-S-2> "
//         "<filename-l-1> <filename-l-2> "
//         "<filename-r-1> <filename-r-2> "
//           "<filename-x-i-1> <filename-x-i-2> ", argv[0]);
//  return -1;
//  }compare_option_h("h1.json", "h2.json");compare_option_S("S1.json", "S2.json");compare_option_l("l1.json", "l2.json");compare_option_r("r1.json", "r2.json");compare_option_x_i("x1.json", "x2.json");//  compare_option_h(argv[1], argv[2]);
//  compare_option_S(argv[3], argv[4]);
//  compare_option_l(argv[5], argv[6]);
//  compare_option_r(argv[7], argv[8]);
//  compare_option_x_i(argv[9], argv[10]);printf("different items number : %d\n", diff_item_num);printf("same items number : %d\n", same_item_num);printf("added items number : %d\n", added_item_num);printf("deleted items number : %d\n", deleted_item_num);return 0;
}

由于一开始使用c去写这个东西,但是最后需要map的支持,为了方便我还是改成了cpp,代码风格比较乱。
这里涉及到一个让人头大的算法——Myers’ diff查分算法,我看了两天才看下来。
这个算法写出来其实挺有意思的,具体可以参考:
Git 是怎样生成 diff 的:Myers 算法 - CJ Ting’s Blog
一个Go的实现
具体论文地址

abi:用json解析和对比linux平台下elf文件相关推荐

  1. linux sybase 自动备份,Linux平台下Sybase数据库备份方法分析.doc

    Linux平台下Sybase数据库备份方法分析 Linux平台下Sybase数据库备份方法分析 摘 要:对于从事信息系统管理的人员来说,掌握数据库的备份方法在工作中尤为重要.当本地数据出错或者磁盘损坏 ...

  2. Linux下的ELF文件、链接、加载与库(含大量图文解析及例程)

    Linux下的ELF文件.链接.加载与库 链接是将将各种代码和数据片段收集并组合为一个单一文件的过程,这个文件可以被加载到内存并执行.链接可以执行与编译时,也就是在源代码被翻译成机器代码时:也可以执行 ...

  3. linux上备份sybase,Linux平台下Sybase数据库备份的方法分析

    龙源期刊网 http://doc.xuehai.net Linux平台下Sybase数据库备份的方法分析 作者:刘君尧王辉静刘云霞 来源:<无线互联科技>2018年第01期 摘要:对于从事 ...

  4. Linux平台下QtCreator集成代码静态分析工具clang-tidy和Clazy

    Linux平台下QtCreator集成代码静态分析工具clang-tidy和Clazy 原文连接: https://blog.csdn.net/wsj18808050/article/details/ ...

  5. linux平台下QtCreator中集成Valgrind系列工具

    linux平台下QtCreator中集成Valgrind系列工具 ###1.valgrind 安装 valgrind 安装 2.打开QtCreator >> Analyze 你就会发现 这 ...

  6. linux oraclerman自动备份,Linux平台下的Oracle自动备份案例(使用RMAN)

    有个童鞋问rman的自动备份脚本程序,我之前有写过exp备份指定方案自动备份案例(Linux平台下的Oracle自动备份案例(使用exp工具)  http://www.linuxidc.com/Lin ...

  7. Linux平台下Eclipse的安装

    Linux平台下Eclipse的安装(2007-06-26 09:50:22)   分类:他山之石 Linux平台下Eclipse的安装 Linux平台下Eclipse的安装2007年06月15日 星 ...

  8. Linux平台下Ntop流量监测安装,并实现Netflow全过程

    Linux平台下Ntop流量监测安装,并实现Netflow全过程 更多原创教学视频详见: http://you.video.sina.com.cn/m/1443650204

  9. linux定时任务每小时_在Linux平台下每5、10或15分钟执行一次定时任务(Cron Job)...

    本文介绍如何在Linux平台下每5.10或15分钟运行一次cron命令,即执行一次定时任务(Cron Job). 前言 Cron job是按指定间隔执行的任务,可以将任务安排为按分钟,小时,每月的某天 ...

最新文章

  1. perl 命令行备注
  2. POJ1083 Moving Tables
  3. 监督学习:KNN(K-近邻)算法实现手写数字识别的三种方法
  4. ZooKeeper程序员指南--使用ZooKeeper开发分布式应用程序
  5. c++和c语言的区别_C与C++傻傻分不清楚,有啥区别,咋用,杂学?
  6. java编译大项目很慢_优化MyEclipse编译速度慢的问题、build、project clean 慢
  7. excel自动保存_做了4个小时的excel未保存怎么办,用这招,快速恢复未保存的数据...
  8. 将本地 jar 安装到本地 maven 仓库
  9. MongoDB 的设计模式策略
  10. IDEA插件jrebel的配置使用
  11. plc仿真实训软件_博途STEP7仿真软件与真实PLC的区别
  12. php投影,投影效果怎么做?PS制作逼真的投影效果
  13. Hive执行报错CannotObtainBlockLengthException: Cannot obtain block length for LocatedBlock
  14. js正则只能输入大于0的正整数
  15. darknet cpp weights模型转换成ONNX模型
  16. 学习笔记之——Java 8
  17. 知识蒸馏 | (1) 知识蒸馏概述
  18. 教你如何一键重装Windows7系统
  19. ACM数论 裴蜀定理(贝祖定理)
  20. 索尼CEO吉田宪一郎:智能手机业务是公司必不可少的一部分

热门文章

  1. 基于HTML+JS实现的简易双色球滚动代码
  2. 在windows2019利用Bonobo Git Server搭建Git服务器
  3. 2017面向对象程序设计(Java)第十七周助教工作总结
  4. 【分层强化学习】HAC源码解读
  5. [Error]新用户第一次启动APP时网络请求失败
  6. centos安装jq
  7. 什么是UART中的FIFO ?
  8. RecyclerView 嵌套RecyclerView 或者 ScrollView当中嵌套RecyclerView ,子View会自动滚动到顶部
  9. 对话本体创始人李俊——有关IEO、DApp、区块链游戏的一些冷思考
  10. html需要电脑什么配置,买电脑主要看什么配置和参数