sql.sh 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. #!/bin/bash
  2. ############################################################################
  3. #
  4. # MODULE: sql.sh
  5. # AUTHOR(S): Glynn Clements
  6. # PURPOSE: run "nm" on every object file, library and executable to
  7. # find dependencies, stored in PostgreSQL database
  8. # COPYRIGHT: (C) 2006 by the GRASS Development Team
  9. #
  10. # This program is free software under the GNU General Public
  11. # License (>=v2). Read the file COPYING that comes with GRASS
  12. # for details.
  13. #
  14. #############################################################################
  15. #
  16. # From: Glynn Clements <glynn at gclements.plus.com>
  17. # Date: Mon, 12 Jun 2006 13:00:25 +0100
  18. #
  19. # Usage: after having compiled GRASS, run "tools/sql.sh `pwd`" from the
  20. # top of the GRASS source tree.
  21. #
  22. # Essentially, the script runs "nm" on every object file, library and
  23. # executable it finds (and "ldd" on all of the executables), processes
  24. # the output with egrep/sed/awk, then imports the results into a
  25. # PostgreSQL database.
  26. #
  27. # "nm" lists the symbol table of an object file, library, or executable,
  28. # indicating whether each symbol is imported into, defined in and/or
  29. # exported from the file.
  30. #
  31. # Most of the database tables record which symbols are imported into or
  32. # exported from which object files, libraries or executables. E.g. the
  33. # "obj_imp" table lists which symbols are imported into which object
  34. # files.
  35. #
  36. # You can then use simple queries such as:
  37. #
  38. # grass=> SELECT object FROM obj_imp WHERE symbol = 'I_get_target' ;
  39. # object
  40. # --------------------------------------------------------------------
  41. # imagery/i.ortho.photo/photo.2image/OBJ.i686-pc-linux-gnu/target.o
  42. # imagery/i.ortho.photo/photo.2target/OBJ.i686-pc-linux-gnu/target.o
  43. # imagery/i.ortho.photo/photo.elev/OBJ.i686-pc-linux-gnu/main.o
  44. # imagery/i.ortho.photo/photo.rectify/OBJ.i686-pc-linux-gnu/target.o
  45. # imagery/i.ortho.photo/photo.target/OBJ.i686-pc-linux-gnu/main.o
  46. # imagery/i.points/OBJ.i686-pc-linux-gnu/target.o
  47. # imagery/i.rectify/OBJ.i686-pc-linux-gnu/target.o
  48. # imagery/i.vpoints/OBJ.i686-pc-linux-gnu/target.o
  49. #
  50. # to discover which files import a given symbol, or more complex queries
  51. # such as:
  52. #
  53. # grass=> SELECT DISTINCT b.object FROM lib_exp a, obj_imp b
  54. # grass-> WHERE a.library = 'libgrass_form.6.1.cvs.so' AND a.symbol = b.symbol ;
  55. # object
  56. # -----------------------------------------------------------
  57. # display/d.what.vect/OBJ.i686-pc-linux-gnu/what.o
  58. # vector/v.digit/OBJ.i686-pc-linux-gnu/attr.o
  59. # vector/v.digit/OBJ.i686-pc-linux-gnu/line.o
  60. # vector/v.what/OBJ.i686-pc-linux-gnu/what.o
  61. # visualization/nviz/src/OBJ.i686-pc-linux-gnu/query_vect.o
  62. # (5 rows)
  63. #
  64. # to discover which files import any symbol defined in a specific
  65. # library. And so on.
  66. #
  67. # For simple "which files use this function" queries, a database lookup
  68. # is quicker and more reliable than grep-ing the source tree.
  69. #
  70. # Assuming that the sql.sh script runs successfully (some of it is
  71. # Linux-specific, other bits are PostgreSQL-specific, but the changes
  72. # required for a different OS or RDBMS should be quite minor), the
  73. # easiest way to figure out what is in a given table (apart from looking
  74. # at the name) is to just sample it, e.g.:
  75. #
  76. # grass=> SELECT * FROM stlib_exp LIMIT 5 ;
  77. # library | object | symbol
  78. # -------------------+------------+---------------
  79. # libgrass_manage.a | add_elem.o | add_element
  80. # libgrass_manage.a | ask.o | ask_in_mapset
  81. # libgrass_manage.a | ask.o | ask_new
  82. # libgrass_manage.a | ask.o | ask_old
  83. # libgrass_manage.a | copyfile.o | copyfile
  84. # (5 rows)
  85. #
  86. tmpdir=/tmp/sql-grass
  87. dbname=grass
  88. if [ -n "$1" ] ; then
  89. builddir="$1"
  90. else
  91. echo "Usage: sql.sh <source directory>" >&2
  92. exit 1
  93. fi
  94. rm -rf "$tmpdir"
  95. mkdir -m 711 "$tmpdir" || exit 1
  96. cd $builddir
  97. ( cd dist.*
  98. LD_LIBRARY_PATH=`pwd`/lib
  99. export LD_LIBRARY_PATH
  100. find . -type f -perm +111 \! -name '*.so.*' \
  101. | while read file ; do ldd $file | sed 's!^!'$file'!' ; done 2>/dev/null \
  102. | sed -e 's/^\.\///' -e 's/ (0x.*)$//' -e 's/ => \(.*\)$/ \1/' -e 's/ => .*$//' \
  103. | fgrep -v 'not a dynamic executable' \
  104. | awk -vOFS='\t' '{print $1,$2,$3 ? $3 : $2}' \
  105. > "$tmpdir/ldd.lst"
  106. find . -type f -perm +111 \! -name '*.so' \
  107. | xargs nm -AD 2>/dev/null \
  108. | egrep ': {8} U ' \
  109. | sed -e 's/:/ /g' -e 's/\.\///' \
  110. | awk -vOFS='\t' '{print $1,$3}' \
  111. > "$tmpdir/prog_imp.lst"
  112. find . -type f -perm +111 \! -name '*.so' \
  113. | xargs nm -AD 2>/dev/null \
  114. | egrep ':[0-9a-f]{8} [BCDGRSTW] ' \
  115. | sed -e 's/:/ /g' -e 's/\.\///' \
  116. | awk -vOFS='\t' '{print $1,$4}' \
  117. > "$tmpdir/prog_exp.lst"
  118. )
  119. find * -type f -name 'lib?*.a' \
  120. | xargs nm -A \
  121. | egrep ':[0-9a-f]{8} [BCDGRSTW] ' \
  122. | sed 's/:/ /g' \
  123. | awk -vOFS='\t' '{print gensub("^[^ ]*/","",1,$1),$2,$5}' \
  124. > "$tmpdir/stlib_exp.lst"
  125. find * -type f -name 'lib?*.so' \
  126. | xargs nm -AD \
  127. | egrep ':[0-9a-f]{8} [BCDGRSTW] ' \
  128. | sed 's/:/ /g' \
  129. | awk -vOFS='\t' '{print gensub("^[^ ]*/","",1,$1),$4}' \
  130. > "$tmpdir/shlib_exp.lst"
  131. find * -type f -name '*.o' \
  132. | xargs nm -A \
  133. | egrep ':[0-9a-f]{8} [BCDGRSTW] ' \
  134. | sed 's/:/ /g' \
  135. | awk -vOFS='\t' '{print $1,$4}' \
  136. > "$tmpdir/obj_exp.lst"
  137. find * -type f -name 'lib?*.a' \
  138. | xargs nm -A \
  139. | egrep ': {8} U ' \
  140. | sed 's/:/ /g' \
  141. | awk -vOFS='\t' '{print gensub("^[^ ]*/","",1,$1),$2,$4}' \
  142. > "$tmpdir/stlib_imp.lst"
  143. find * -type f -name 'lib?*.so' \
  144. | xargs nm -AD \
  145. | egrep ': {8} U ' \
  146. | sed 's/:/ /g' \
  147. | awk -vOFS='\t' '{print gensub("^[^ ]*/","",1,$1),$3}' \
  148. > "$tmpdir/shlib_imp.lst"
  149. find * -type f -name '*.o' \
  150. | xargs nm -A \
  151. | egrep ': {8} U ' \
  152. | sed 's/:/ /g' \
  153. | awk -vOFS='\t' '{print $1,$3}' \
  154. > "$tmpdir/obj_imp.lst"
  155. libs=`awk '{print $3}' "$tmpdir/ldd.lst" | uniq | sort | uniq`
  156. nm -AD $libs \
  157. | egrep ':[0-9a-f]{8} [TWDRC] ' \
  158. | sed 's/:/ /g' \
  159. | awk -vOFS='\t' '{print gensub("^[^ ]*/","",1,$1),$4}' \
  160. > "$tmpdir/libs.lst"
  161. cat > "$tmpdir/ansi.lst" <<EOF
  162. abort
  163. asctime
  164. atexit
  165. atof
  166. atoi
  167. atol
  168. bsearch
  169. calloc
  170. clearerr
  171. ctime
  172. exit
  173. fclose
  174. feof
  175. ferror
  176. fflush
  177. fgetc
  178. fgetpos
  179. fgets
  180. fopen
  181. fprintf
  182. fputc
  183. fputs
  184. fread
  185. free
  186. freopen
  187. fscanf
  188. fseek
  189. fsetpos
  190. ftell
  191. fwrite
  192. getc
  193. getchar
  194. getenv
  195. gets
  196. isalnum
  197. isalpha
  198. isdigit
  199. islower
  200. isspace
  201. ldiv
  202. localtime
  203. longjmp
  204. malloc
  205. memcmp
  206. memcpy
  207. memmove
  208. memset
  209. perror
  210. printf
  211. putc
  212. putchar
  213. puts
  214. qsort
  215. rand
  216. realloc
  217. remove
  218. rename
  219. rewind
  220. scanf
  221. setbuf
  222. setjmp
  223. setvbuf
  224. signal
  225. sprintf
  226. srand
  227. sscanf
  228. stderr
  229. stdin
  230. stdout
  231. strcat
  232. strchr
  233. strcmp
  234. strcpy
  235. strcspn
  236. strerror
  237. strftime
  238. strlen
  239. strncat
  240. strncmp
  241. strncpy
  242. strpbrk
  243. strrchr
  244. strspn
  245. strstr
  246. strtod
  247. strtok
  248. strtol
  249. time
  250. tmpfile
  251. tmpnam
  252. tolower
  253. toupper
  254. ungetc
  255. vfprintf
  256. vsprintf
  257. EOF
  258. dropdb "$dbname"
  259. createdb "$dbname"
  260. psql -n -q -d "$dbname" << EOF
  261. -- ----------------------------------------------------------------------
  262. CREATE TABLE stlib_exp (
  263. library VARCHAR(80) NOT NULL,
  264. object VARCHAR(40) NOT NULL,
  265. symbol VARCHAR(256) NOT NULL
  266. ) ;
  267. \copy stlib_exp FROM '$tmpdir/stlib_exp.lst'
  268. CREATE TABLE shlib_exp (
  269. library VARCHAR(80) NOT NULL,
  270. symbol VARCHAR(256) NOT NULL
  271. ) ;
  272. \copy shlib_exp FROM '$tmpdir/shlib_exp.lst'
  273. CREATE TABLE obj_exp (
  274. object VARCHAR(100) NOT NULL,
  275. symbol VARCHAR(256) NOT NULL
  276. ) ;
  277. \copy obj_exp FROM '$tmpdir/obj_exp.lst'
  278. CREATE TABLE stlib_imp (
  279. library VARCHAR(80) NOT NULL,
  280. object VARCHAR(40) NOT NULL,
  281. symbol VARCHAR(256) NOT NULL
  282. ) ;
  283. \copy stlib_imp FROM '$tmpdir/stlib_imp.lst'
  284. CREATE TABLE shlib_imp (
  285. library VARCHAR(80) NOT NULL,
  286. symbol VARCHAR(256) NOT NULL
  287. ) ;
  288. \copy shlib_imp FROM '$tmpdir/shlib_imp.lst'
  289. CREATE TABLE obj_imp (
  290. object VARCHAR(100) NOT NULL,
  291. symbol VARCHAR(256) NOT NULL
  292. ) ;
  293. \copy obj_imp FROM '$tmpdir/obj_imp.lst'
  294. CREATE TABLE prog_imp (
  295. program VARCHAR(80) NOT NULL,
  296. symbol VARCHAR(256) NOT NULL
  297. ) ;
  298. \copy prog_imp FROM '$tmpdir/prog_imp.lst'
  299. CREATE TABLE prog_exp (
  300. program VARCHAR(80) NOT NULL,
  301. symbol VARCHAR(256) NOT NULL
  302. ) ;
  303. \copy prog_exp FROM '$tmpdir/prog_exp.lst'
  304. CREATE TABLE libs (
  305. library VARCHAR(80) NOT NULL,
  306. symbol VARCHAR(1000) NOT NULL
  307. ) ;
  308. \copy libs FROM '$tmpdir/libs.lst'
  309. CREATE TABLE ldd (
  310. program VARCHAR(80) NOT NULL,
  311. library VARCHAR(80) NOT NULL,
  312. path VARCHAR(256)
  313. ) ;
  314. \copy ldd FROM '$tmpdir/ldd.lst'
  315. CREATE TABLE ansi (
  316. symbol VARCHAR(256) NOT NULL
  317. ) ;
  318. \copy ansi FROM '$tmpdir/ansi.lst'
  319. -- ----------------------------------------------------------------------
  320. SELECT DISTINCT library, symbol
  321. INTO TABLE lib_exp
  322. FROM stlib_exp
  323. UNION
  324. SELECT DISTINCT library, symbol
  325. FROM shlib_exp ;
  326. CREATE TABLE duplicates AS
  327. SELECT DISTINCT symbol
  328. FROM lib_exp
  329. GROUP BY symbol
  330. HAVING COUNT(*) > 1 ;
  331. CREATE TABLE duplicates2 AS
  332. SELECT *
  333. FROM lib_exp
  334. WHERE symbol IN (
  335. SELECT symbol
  336. FROM duplicates
  337. ) ;
  338. SELECT DISTINCT library, symbol
  339. INTO TABLE lib_imp
  340. FROM stlib_imp
  341. UNION
  342. SELECT DISTINCT library, symbol
  343. FROM shlib_imp ;
  344. CREATE TABLE imports AS
  345. SELECT a.library, a.symbol
  346. FROM lib_imp a
  347. WHERE NOT EXISTS (
  348. SELECT b.library, b.symbol
  349. FROM lib_exp b
  350. WHERE b.symbol = a.symbol
  351. AND b.library = a.library
  352. ) ;
  353. CREATE TABLE defined AS
  354. SELECT DISTINCT symbol
  355. FROM lib_exp ;
  356. CREATE TABLE used AS
  357. SELECT DISTINCT symbol
  358. FROM imports ;
  359. CREATE TABLE undefined AS
  360. SELECT symbol
  361. FROM used u
  362. WHERE NOT EXISTS (
  363. SELECT *
  364. FROM defined d
  365. WHERE d.symbol = u.symbol
  366. ) ;
  367. SELECT symbol
  368. INTO TABLE undefined_1
  369. FROM undefined
  370. EXCEPT
  371. SELECT b.symbol
  372. FROM undefined a, libs b
  373. WHERE a.symbol = b.symbol ;
  374. CREATE TABLE undefined_2 AS
  375. SELECT i.symbol, i.object, i.library
  376. FROM stlib_imp i, undefined_1 u
  377. WHERE i.symbol = u.symbol ;
  378. CREATE TABLE depends AS
  379. SELECT i.library AS im_lib,
  380. i.symbol AS symbol,
  381. e.library AS ex_lib
  382. FROM imports i, lib_exp e
  383. WHERE i.symbol = e.symbol ;
  384. CREATE TABLE lib_deps AS
  385. SELECT DISTINCT im_lib, ex_lib
  386. FROM depends
  387. WHERE im_lib <> ex_lib ;
  388. CREATE TABLE lib_deps_1 AS
  389. SELECT a.im_lib,
  390. a.ex_lib AS in_lib,
  391. b.ex_lib
  392. FROM lib_deps a, lib_deps b
  393. WHERE a.ex_lib = b.im_lib ;
  394. CREATE TABLE lib_deps_2 AS
  395. SELECT a.im_lib,
  396. a.in_lib AS in1_lib,
  397. a.ex_lib AS in2_lib,
  398. b.ex_lib
  399. FROM lib_deps_1 a, lib_deps b
  400. WHERE a.ex_lib = b.im_lib
  401. AND a.im_lib <> a.ex_lib ;
  402. SELECT im_lib, ex_lib
  403. INTO TABLE lib_deps_trans
  404. FROM lib_deps
  405. UNION
  406. SELECT im_lib, ex_lib
  407. FROM lib_deps_1
  408. UNION
  409. SELECT im_lib, ex_lib
  410. FROM lib_deps_2 ;
  411. CREATE TABLE prog_libs AS
  412. SELECT DISTINCT a.program, b.library
  413. FROM prog_imp a, lib_exp b
  414. WHERE a.symbol = b.symbol ;
  415. SELECT DISTINCT a.symbol
  416. INTO TABLE libc
  417. FROM prog_imp a, libs b
  418. WHERE a.symbol = b.symbol
  419. AND b.library = 'libc.so.6'
  420. UNION
  421. SELECT DISTINCT a.symbol
  422. FROM imports a, libs b
  423. WHERE a.symbol = b.symbol
  424. AND b.library = 'libc.so.6' ;
  425. SELECT symbol
  426. INTO nonansi
  427. FROM libc
  428. WHERE symbol !~ '_.*'
  429. EXCEPT
  430. SELECT symbol
  431. FROM ansi ;
  432. CREATE TABLE nonansi_progs AS
  433. SELECT a.symbol, COUNT(*)
  434. FROM prog_imp a, nonansi b
  435. WHERE a.symbol = b.symbol
  436. AND a.program NOT LIKE 'bin/%'
  437. GROUP BY a.symbol ;
  438. CREATE TABLE nonansi_libs AS
  439. SELECT a.symbol, COUNT(*)
  440. FROM imports a, nonansi b
  441. WHERE a.symbol = b.symbol
  442. GROUP BY a.symbol ;
  443. SELECT symbol
  444. INTO TABLE nonansi_counts
  445. FROM nonansi_progs
  446. UNION
  447. SELECT symbol
  448. FROM nonansi_libs ;
  449. ALTER TABLE nonansi_counts
  450. ADD COLUMN progs INTEGER ;
  451. ALTER TABLE nonansi_counts
  452. ADD COLUMN libs INTEGER ;
  453. UPDATE nonansi_counts
  454. SET progs = 0, libs = 0 ;
  455. UPDATE nonansi_counts
  456. SET progs = b.count
  457. FROM nonansi_progs b
  458. WHERE nonansi_counts.symbol = b.symbol ;
  459. UPDATE nonansi_counts
  460. SET libs = c.count
  461. FROM nonansi_libs c
  462. WHERE nonansi_counts.symbol = c.symbol;
  463. -- SELECT a.symbol, a.program
  464. -- FROM prog_imp a, nonansi_progs b
  465. -- WHERE a.symbol = b.symbol
  466. -- AND a.program NOT LIKE 'bin/%'
  467. -- ORDER BY b.count DESC, b.symbol ;
  468. -- SELECT symbol, library
  469. -- FROM duplicates2
  470. -- ORDER BY symbol ;
  471. -- SELECT a.im_lib, a.ex_lib
  472. -- FROM lib_deps a, lib_deps b
  473. -- WHERE a.ex_lib = b.im_lib
  474. -- AND b.ex_lib = a.im_lib ;
  475. -- SELECT * FROM lib_deps_2
  476. -- WHERE im_lib = ex_lib ;
  477. -- SELECT * FROM lib_deps_1
  478. -- WHERE im_lib = ex_lib ;
  479. -- SELECT im_lib FROM lib_deps_trans
  480. -- WHERE im_lib = ex_lib ;
  481. -- SELECT a.program, a.library
  482. -- FROM ldd a
  483. -- WHERE a.library LIKE 'libgrass_%.so'
  484. -- AND a.library NOT IN (
  485. -- SELECT b.library
  486. -- FROM prog_libs b
  487. -- WHERE b.program = a.program
  488. -- ) ;
  489. -- ----------------------------------------------------------------------
  490. EOF