• Cairo介绍及源码构建安装(2)


    接前一篇文章:Cairo介绍及源码构建安装(1)

    四、Cairo构建与安装

    1. 源码修改

    (1)修改lookup-symbol.c

    修改命令如下:

    sed 's/PTR/void */' -i util/cairo-trace/lookup-symbol.c

    这句的意思是将util/cairo-trace/lookup-symbol.c文件中所有地方的“PTR”替换为“void *”。

    lookup-symbol.c文件原始内容如下:

    1. /* cairo-trace - a utility to record and replay calls to the Cairo library.
    2. *
    3. * Copyright © 2008 Chris Wilson
    4. *
    5. * This program is free software: you can redistribute it and/or modify
    6. * it under the terms of the GNU General Public License as published by
    7. * the Free Software Foundation, either version 3 of the License, or
    8. * (at your option) any later version.
    9. *
    10. * This program is distributed in the hope that it will be useful,
    11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13. * GNU General Public License for more details.
    14. *
    15. * You should have received a copy of the GNU General Public License
    16. * along with this program. If not, see .
    17. */
    18. /*
    19. * A less hacky utility to lookup the debug strings for a particular
    20. * .text address.
    21. * Derived from backtrace-symbols.c in cairo by Chris Wilson.
    22. */
    23. /*
    24. A hacky replacement for backtrace_symbols in glibc
    25. backtrace_symbols in glibc looks up symbols using dladdr which is limited
    26. in the symbols that it sees. libbacktracesymbols opens the executable and
    27. shared libraries using libbfd and will look up backtrace information using
    28. the symbol table and the dwarf line information.
    29. It may make more sense for this program to use libelf instead of libbfd.
    30. However, I have not investigated that yet.
    31. Derived from addr2line.c from GNU Binutils by Jeff Muizelaar
    32. Copyright 2007 Jeff Muizelaar
    33. */
    34. /* addr2line.c -- convert addresses to line number and function name
    35. Copyright 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
    36. Contributed by Ulrich Lauther
    37. This file was part of GNU Binutils.
    38. */
    39. #include "config.h"
    40. #define true 1
    41. #define false 0
    42. #include "lookup-symbol.h"
    43. #include
    44. #include
    45. #include
    46. #include
    47. #include
    48. #include
    49. #if HAVE_BFD
    50. #include
    51. struct symtab {
    52. bfd *bfd;
    53. asymbol **syms;
    54. };
    55. struct symbol {
    56. int found;
    57. bfd_vma pc;
    58. struct symtab *symtab;
    59. const char *filename;
    60. const char *functionname;
    61. unsigned int line;
    62. };
    63. static void
    64. _symtab_fini (struct symtab *symtab)
    65. {
    66. free (symtab->syms);
    67. if (symtab->bfd != NULL)
    68. bfd_close (symtab->bfd);
    69. }
    70. /* Read in the symbol table. */
    71. static int
    72. _symtab_init (struct symtab *symtab, const char *filename)
    73. {
    74. char **matching;
    75. long symcount;
    76. unsigned int size;
    77. symtab->bfd = NULL;
    78. symtab->syms = NULL;
    79. symtab->bfd = bfd_openr (filename, NULL);
    80. if (symtab->bfd == NULL)
    81. goto BAIL;
    82. if (bfd_check_format (symtab->bfd, bfd_archive))
    83. goto BAIL;
    84. if (! bfd_check_format_matches (symtab->bfd, bfd_object, &matching))
    85. goto BAIL;
    86. symcount = bfd_read_minisymbols (symtab->bfd, false, (PTR) &symtab->syms, &size);
    87. if (symcount == 0) {
    88. symcount = bfd_read_minisymbols (symtab->bfd, true /* dynamic */ ,
    89. (PTR) &symtab->syms, &size);
    90. }
    91. if (symcount < 0)
    92. goto BAIL;
    93. if ((bfd_get_file_flags (symtab->bfd) & HAS_SYMS) == 0)
    94. goto BAIL;
    95. return 1;
    96. BAIL:
    97. _symtab_fini (symtab);
    98. return 0;
    99. }
    100. /* Look for an address in a section.
    101. * This is called via bfd_map_over_sections.
    102. */
    103. static void
    104. find_address_in_section (bfd *abfd,
    105. asection *section,
    106. void *data)
    107. {
    108. bfd_vma vma;
    109. bfd_size_type size;
    110. struct symbol *symbol = data;
    111. struct symtab *symtab = symbol->symtab;
    112. if (symbol->found)
    113. return;
    114. if ((bfd_section_flags (section) & SEC_ALLOC) == 0)
    115. return;
    116. vma = bfd_section_vma (section);
    117. if (symbol->pc < vma)
    118. return;
    119. size = bfd_section_size (section);
    120. if (symbol->pc >= vma + size)
    121. return;
    122. symbol->found = bfd_find_nearest_line (symtab->bfd, section,
    123. symtab->syms,
    124. symbol->pc - vma,
    125. &symbol->filename,
    126. &symbol->functionname,
    127. &symbol->line);
    128. }
    129. static void
    130. _symbol_fini (struct symbol *symbol)
    131. {
    132. }
    133. static void
    134. _symbol_init (struct symbol *symbol, struct symtab *symtab, bfd_vma addr)
    135. {
    136. symbol->found = false;
    137. symbol->symtab = symtab;
    138. symbol->pc = addr;
    139. }
    140. static void
    141. _symbol_print (struct symbol *symbol, char *buf, int buflen, const char *filename)
    142. {
    143. const char *name, *h;
    144. char path[1024];
    145. if (! symbol->found)
    146. return;
    147. name = symbol->functionname;
    148. if (name == NULL || *name == '\0')
    149. name = "??";
    150. if (symbol->filename != NULL)
    151. filename = symbol->filename;
    152. if (strcmp (filename, "/proc/self/exe") == 0) {
    153. int len = readlink ("/proc/self/exe", path, sizeof (path) - 1);
    154. if (len != -1) {
    155. path[len] = '\0';
    156. filename = path;
    157. }
    158. }
    159. h = strrchr (filename, '/');
    160. if (h != NULL)
    161. filename = h + 1;
    162. if (symbol->line) {
    163. snprintf (buf, buflen, "%s() [%s:%u]",
    164. name, filename, symbol->line);
    165. } else {
    166. snprintf (buf, buflen, "%s() [%s]", name, filename);
    167. }
    168. }
    169. #endif
    170. struct file_match {
    171. const char *file;
    172. ElfW(Addr) address;
    173. ElfW(Addr) base;
    174. void *hdr;
    175. };
    176. static int
    177. find_matching_file (struct dl_phdr_info *info, size_t size, void *data)
    178. {
    179. struct file_match *match = data;
    180. /* This code is modeled from Gfind_proc_info-lsb.c:callback() from libunwind */
    181. long n;
    182. const ElfW(Phdr) *phdr;
    183. ElfW(Addr) load_base = info->dlpi_addr;
    184. phdr = info->dlpi_phdr;
    185. for (n = info->dlpi_phnum; --n >= 0; phdr++) {
    186. if (phdr->p_type == PT_LOAD) {
    187. ElfW(Addr) vaddr = phdr->p_vaddr + load_base;
    188. if (match->address >= vaddr &&
    189. match->address < vaddr + phdr->p_memsz)
    190. {
    191. /* we found a match */
    192. match->file = info->dlpi_name;
    193. match->base = info->dlpi_addr;
    194. return 1;
    195. }
    196. }
    197. }
    198. return 0;
    199. }
    200. struct symbol_cache_entry {
    201. const void *ptr;
    202. struct symbol_cache_entry *hash_prev, *hash_next;
    203. char name[0];
    204. };
    205. static struct symbol_cache_entry *symbol_cache_hash[13477];
    206. static pthread_mutex_t symbol_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
    207. char *
    208. lookup_symbol (char *buf, int buflen, const void *ptr)
    209. {
    210. struct file_match match;
    211. #if HAVE_BFD
    212. struct symtab symtab;
    213. struct symbol symbol;
    214. #endif
    215. struct symbol_cache_entry *cache;
    216. int bucket;
    217. int len;
    218. bucket = (uintptr_t) ptr % (sizeof (symbol_cache_hash) / sizeof (symbol_cache_hash[0]));
    219. pthread_mutex_lock (&symbol_cache_mutex);
    220. for (cache = symbol_cache_hash[bucket];
    221. cache != NULL;
    222. cache = cache->hash_next)
    223. {
    224. if (cache->ptr == ptr) {
    225. if (cache->hash_prev != NULL) {
    226. cache->hash_prev->hash_next = cache->hash_next;
    227. if (cache->hash_next != NULL)
    228. cache->hash_next->hash_prev = cache->hash_prev;
    229. cache->hash_prev = NULL;
    230. cache->hash_next = symbol_cache_hash[bucket];
    231. symbol_cache_hash[bucket]->hash_prev = cache;
    232. symbol_cache_hash[bucket] = cache;
    233. }
    234. pthread_mutex_unlock (&symbol_cache_mutex);
    235. return cache->name;
    236. }
    237. }
    238. pthread_mutex_unlock (&symbol_cache_mutex);
    239. match.file = NULL;
    240. match.address = (ElfW(Addr)) ptr;
    241. dl_iterate_phdr (find_matching_file, &match);
    242. snprintf (buf, buflen, "0x%llx",
    243. (long long unsigned int) match.address);
    244. if (match.file == NULL || *match.file == '\0')
    245. match.file = "/proc/self/exe";
    246. #if HAVE_BFD
    247. if (_symtab_init (&symtab, match.file)) {
    248. _symbol_init (&symbol, &symtab, match.address - match.base);
    249. bfd_map_over_sections (symtab.bfd, find_address_in_section, &symbol);
    250. if (symbol.found)
    251. _symbol_print (&symbol, buf, buflen, match.file);
    252. _symbol_fini (&symbol);
    253. _symtab_fini (&symtab);
    254. }
    255. #endif
    256. len = strlen (buf);
    257. cache = malloc (sizeof (struct symbol_cache_entry) + len + 1);
    258. if (cache != NULL) {
    259. cache->ptr = ptr;
    260. memcpy (cache->name, buf, len + 1);
    261. pthread_mutex_lock (&symbol_cache_mutex);
    262. cache->hash_prev = NULL;
    263. cache->hash_next = symbol_cache_hash[bucket];
    264. if (symbol_cache_hash[bucket] != NULL)
    265. symbol_cache_hash[bucket]->hash_prev = cache;
    266. symbol_cache_hash[bucket] = cache;
    267. pthread_mutex_unlock (&symbol_cache_mutex);
    268. }
    269. return buf;
    270. }

    真正需要替换的只有2处,代码片段如下:

    1. symcount = bfd_read_minisymbols (symtab->bfd, false, (PTR) &symtab->syms, &size);
    2. if (symcount == 0) {
    3. symcount = bfd_read_minisymbols (symtab->bfd, true /* dynamic */ ,
    4. (PTR) &symtab->syms, &size);
    5. }
    6. if (symcount < 0)
    7. goto BAIL;

    执行命令后,这段内容变为:

    1. symcount = bfd_read_minisymbols (symtab->bfd, false, (void *) &symtab->syms, &size);
    2. if (symcount == 0) {
    3. symcount = bfd_read_minisymbols (symtab->bfd, true /* dynamic */ ,
    4. (void *) &symtab->syms, &size);
    5. }
    6. if (symcount < 0)
    7. goto BAIL;

    (2)修改cairo-script-interpreter.pc.in

    修改命令如下:

    1. sed -e "/@prefix@/a exec_prefix=@exec_prefix@" \
    2. -i util/cairo-script/cairo-script-interpreter.pc.in

    这句的意思是在util/cairo-script/cairo-script-interpreter.pc.in文件中找到包含“@prefix@”的一行,在其下方添加一行内容:exec_prefix=@exec_prefix@。

    cairo-script-interpreter.pc.in文件原始内容如下:

    1. prefix=@prefix@
    2. libdir=@libdir@
    3. includedir=@includedir@
    4. Name: cairo-script-interpreter
    5. Description: script surface backend for cairo graphics library
    6. Version: @VERSION@
    7. Requires: cairo
    8. Libs: -L${libdir} -lcairo-script-interpreter
    9. Cflags: -I${includedir}/cairo

    执行命令后,文件内容变为:

    1. prefix=@prefix@
    2. exec_prefix=@exec_prefix@
    3. libdir=@libdir@
    4. includedir=@includedir@
    5. Name: cairo-script-interpreter
    6. Description: script surface backend for cairo graphics library
    7. Version: @VERSION@
    8. Requires: cairo
    9. Libs: -L${libdir} -lcairo-script-interpreter
    10. Cflags: -I${includedir}/cairo

  • 相关阅读:
    《Linux》day5--ssh——ssh登录与scp传文件
    图像识别在自动驾驶汽车中的多传感器融合技术
    MySQL数据库备份与恢复:物理备份和逻辑备份详解
    Invalid bound statement (not found)出现的原因和解决方法
    Flink 流处理API-Window API
    榛子树搜索算法(Hazelnut tree search algorithm,HTS)附matlab代码
    鸿蒙系统调研适配
    gerrit部署使用
    Linux虚拟机安装及Docker常用操作
    Windows系统如何临时关闭“Windows安全中心实时保护”
  • 原文地址:https://blog.csdn.net/phmatthaus/article/details/133307725