├── myldd ├── README.md ├── Makefile ├── my_ldd.h ├── LICENSE └── my_ldd.cpp /myldd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codercheng/myLdd/master/myldd -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # myLdd 2 | a ldd-like tool 3 | 4 | # attention 5 | make之前,确保安装了libelf,libelf-devel,否则make会报错。 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: myldd 2 | 3 | myldd: my_ldd.cpp my_ldd.h 4 | g++ -g -Wall $< -o $@ -lelf 5 | 6 | 7 | clean: 8 | rm -f myldd 9 | -------------------------------------------------------------------------------- /my_ldd.h: -------------------------------------------------------------------------------- 1 | #ifndef _DBG_DEP_H 2 | #define _DBG_DEP_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | class MyLdd { 11 | public: 12 | MyLdd(string filename); 13 | vector &GetSharedLibs(); 14 | vector &GetMissedLibs(); 15 | private: 16 | int getDepsInfo(string filename, vector &sharedLibName, vector &rpath); 17 | void setSearchPath(); 18 | void getDeps(); 19 | private: 20 | map visited; 21 | string filename; 22 | vector searchPath; 23 | vector rpath; 24 | vector missLibs; 25 | vector depsLibs; 26 | }; 27 | 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 simon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /my_ldd.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include "my_ldd.h" 17 | using namespace std; 18 | 19 | static 20 | bool fileExist(string filepath) { 21 | return !access(filepath.c_str(), F_OK); 22 | } 23 | static 24 | bool isDir(string dirpath) { 25 | struct stat s; 26 | if (stat(dirpath.c_str(), &s) == 0) { 27 | if (S_ISDIR(s.st_mode)) { 28 | return true; 29 | } 30 | } 31 | return false; 32 | } 33 | 34 | static 35 | vector splitString(string str) { 36 | vector ret; 37 | size_t begin = 0; 38 | while(1) { 39 | size_t pos = str.find(":", begin); 40 | if (pos == string::npos) { 41 | ret.push_back(str.substr(begin)); 42 | return ret; 43 | } 44 | ret.push_back(str.substr(begin, pos-begin)); 45 | begin = pos + 1; 46 | } 47 | } 48 | 49 | /* path included in /etc/ld.so.conf*/ 50 | static 51 | vector getPathInFile(string filename) { 52 | vector ret; 53 | FILE *fp = fopen(filename.c_str(), "r"); 54 | if (fp == NULL) { 55 | return ret; 56 | } 57 | char buf[256]; 58 | while(!feof(fp)) { 59 | memset(buf, 0, sizeof(buf)); 60 | if (fgets(buf, sizeof(buf), fp) == NULL) 61 | break; 62 | char *p = buf; 63 | /*rm whitespaces*/ 64 | while(p!='\0' && *p == ' ') 65 | p++; 66 | char *e = strchr(p, ' '); 67 | if (e != NULL) { 68 | *e = '\0'; 69 | } 70 | buf[strlen(buf)-1] = '\0'; 71 | //printf("path:-%s-\n", p); 72 | string path(p); 73 | if (isDir(path)) { 74 | ret.push_back(path); 75 | } 76 | } 77 | 78 | fclose(fp); 79 | return ret; 80 | } 81 | 82 | static 83 | vector getLdSoPath() { 84 | vector ret; 85 | vector files; 86 | files.push_back("/etc/ld.so.conf"); 87 | struct dirent *dent; 88 | struct stat s; 89 | DIR *dir; 90 | 91 | dir = opendir("/etc/ld.so.conf.d/"); 92 | if (dir == NULL) { 93 | return ret; 94 | } 95 | while((dent = readdir(dir)) != NULL) { 96 | if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) 97 | continue; 98 | string path; 99 | path = string("/etc/ld.so.conf.d/") + string(dent->d_name); 100 | lstat(path.c_str(), &s); 101 | if (S_ISREG(s.st_mode)) { 102 | files.push_back(path); 103 | } 104 | } 105 | closedir(dir); 106 | size_t i; 107 | vector tmp; 108 | for (i=0; ifilename = filename; 119 | setSearchPath(); 120 | } 121 | 122 | vector &MyLdd::GetSharedLibs() { 123 | getDeps(); 124 | return depsLibs; 125 | } 126 | 127 | vector &MyLdd::GetMissedLibs() { 128 | return missLibs; 129 | } 130 | 131 | void MyLdd::getDeps() { 132 | queue q; 133 | 134 | q.push(filename); 135 | visited[filename] = true; 136 | 137 | while(!q.empty()) { 138 | vector sharedLibs; 139 | vector rpath_tmp; 140 | vector spath; 141 | 142 | string newfilename = q.front(); 143 | q.pop(); 144 | getDepsInfo(newfilename, sharedLibs, rpath_tmp); 145 | rpath.insert(rpath.begin(), rpath_tmp.begin(), rpath_tmp.end()); 146 | spath = rpath; 147 | spath.insert(spath.end(), searchPath.begin(), searchPath.end()); 148 | size_t i; 149 | size_t j; 150 | #if 0 151 | for (i=0; i tmp = getLdSoPath(); 187 | searchPath.insert(searchPath.begin(), tmp.begin(), tmp.end()); 188 | /*/etc/ld.so.conf /etc/ld.so.conf.d*/ 189 | searchPath.push_back("/lib64"); 190 | searchPath.push_back("/usr/lib64"); 191 | searchPath.push_back("/lib"); 192 | searchPath.push_back("/usr/lib"); 193 | searchPath.push_back("/usr/local/lib"); 194 | } 195 | 196 | int MyLdd::getDepsInfo(string filename, vector &sharedLibName, vector& rpath) { 197 | int ret = -1; 198 | int fd; 199 | int cnt = 0; 200 | Elf *elf; 201 | GElf_Ehdr ehdr; 202 | GElf_Shdr shdr; 203 | Elf_Data *data_dynamic = NULL; 204 | Elf_Data *data_dynstr = NULL; 205 | 206 | Elf_Scn *sec_dynamic = NULL; /*.dynamic section*/ 207 | Elf_Scn *sec_dynstr = NULL; /*.dynstr section*/ 208 | Elf_Scn *sec = NULL; 209 | GElf_Dyn *dyn = NULL; 210 | 211 | Elf_Kind ek; 212 | 213 | elf_version(EV_CURRENT); 214 | 215 | fd = open(filename.c_str(), O_RDONLY); 216 | if (!fd) { 217 | ret = -1; 218 | goto out; 219 | } 220 | 221 | elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); 222 | if (elf == NULL) { 223 | fprintf(stderr, "%s: cannot read %s ELF file.\n", __func__, filename.c_str()); 224 | ret = -1; 225 | goto out_close; 226 | } 227 | 228 | ek = elf_kind(elf); 229 | if (ek != ELF_K_ELF) { 230 | ret = -1; 231 | goto out_elf; 232 | } 233 | 234 | if (gelf_getehdr(elf, &ehdr) == NULL) { 235 | fprintf(stderr, "%s: cannot get elf header.\n", __func__); 236 | ret = -1; 237 | goto out_elf; 238 | } 239 | 240 | /* Elf is corrupted/truncated, avoid calling elf_strptr. */ 241 | if (!elf_rawdata(elf_getscn(elf, ehdr.e_shstrndx), NULL)) 242 | goto out_elf; 243 | 244 | while ((sec = elf_nextscn(elf, sec)) != NULL) { 245 | char *str; 246 | 247 | gelf_getshdr(sec, &shdr); 248 | str = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name); 249 | if (!strcmp(".dynamic", str)) { 250 | sec_dynamic = sec; 251 | break; 252 | } 253 | if (!strcmp(".dynstr", str)) { 254 | sec_dynstr = sec; 255 | } 256 | } 257 | if (!sec_dynamic || !sec_dynstr) { 258 | ret = -1; 259 | goto out_elf; 260 | } 261 | 262 | data_dynamic = elf_getdata(sec_dynamic, NULL); 263 | if (data_dynamic == NULL) { 264 | ret = -1; 265 | goto out_elf; 266 | } 267 | 268 | data_dynstr = elf_getdata(sec_dynstr, NULL); 269 | if (data_dynstr == NULL) { 270 | ret = -1; 271 | goto out_elf; 272 | } 273 | 274 | dyn = (GElf_Dyn *)malloc(sizeof(GElf_Dyn)); 275 | 276 | gelf_getdyn(data_dynamic, 0, dyn); 277 | for (;dyn->d_tag != DT_NULL; ) { 278 | if (dyn->d_tag == DT_NEEDED) { 279 | sharedLibName.push_back(string((char *)(data_dynstr->d_buf)+dyn->d_un.d_val)); 280 | } 281 | else if (dyn->d_tag == DT_RPATH) { 282 | rpath = splitString(string((char *)(data_dynstr->d_buf)+dyn->d_un.d_val)); 283 | } 284 | else if (dyn->d_tag == DT_SONAME) { 285 | } 286 | gelf_getdyn(data_dynamic, ++cnt, dyn); 287 | if (dyn->d_tag == DT_NULL) 288 | break; 289 | } 290 | free(dyn); 291 | ret = 0; 292 | 293 | out_elf: 294 | elf_end(elf); 295 | out_close: 296 | close(fd); 297 | out: 298 | return ret; 299 | } 300 | 301 | #if 1 302 | int main(int argc, char *argv[]) { 303 | if (argc != 2) { 304 | fprintf(stderr, "usage: ./myldd executable-file\n"); 305 | return -1; 306 | } 307 | vector libs; 308 | vector mlibs; 309 | 310 | MyLdd deps(argv[1]); 311 | libs = deps.GetSharedLibs(); 312 | 313 | size_t i; 314 | for (i=0; i path; 325 | path = getLdSoPath(); 326 | //size_t i; 327 | for (i=0; i