接前一篇文章: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文件原始内容如下:
- /* cairo-trace - a utility to record and replay calls to the Cairo library.
- *
- * Copyright © 2008 Chris Wilson
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see
. - */
-
- /*
- * A less hacky utility to lookup the debug strings for a particular
- * .text address.
- * Derived from backtrace-symbols.c in cairo by Chris Wilson.
- */
-
- /*
- A hacky replacement for backtrace_symbols in glibc
- backtrace_symbols in glibc looks up symbols using dladdr which is limited
- in the symbols that it sees. libbacktracesymbols opens the executable and
- shared libraries using libbfd and will look up backtrace information using
- the symbol table and the dwarf line information.
- It may make more sense for this program to use libelf instead of libbfd.
- However, I have not investigated that yet.
- Derived from addr2line.c from GNU Binutils by Jeff Muizelaar
- Copyright 2007 Jeff Muizelaar
- */
-
- /* addr2line.c -- convert addresses to line number and function name
- Copyright 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
- Contributed by Ulrich Lauther
- This file was part of GNU Binutils.
- */
-
- #include "config.h"
-
- #define true 1
- #define false 0
-
- #include "lookup-symbol.h"
-
- #include
- #include
- #include
- #include
- #include
- #include
-
- #if HAVE_BFD
- #include
-
- struct symtab {
- bfd *bfd;
- asymbol **syms;
- };
-
- struct symbol {
- int found;
- bfd_vma pc;
- struct symtab *symtab;
- const char *filename;
- const char *functionname;
- unsigned int line;
- };
-
-
- static void
- _symtab_fini (struct symtab *symtab)
- {
- free (symtab->syms);
- if (symtab->bfd != NULL)
- bfd_close (symtab->bfd);
- }
-
- /* Read in the symbol table. */
- static int
- _symtab_init (struct symtab *symtab, const char *filename)
- {
- char **matching;
- long symcount;
- unsigned int size;
-
- symtab->bfd = NULL;
- symtab->syms = NULL;
-
- symtab->bfd = bfd_openr (filename, NULL);
- if (symtab->bfd == NULL)
- goto BAIL;
-
- if (bfd_check_format (symtab->bfd, bfd_archive))
- goto BAIL;
-
- if (! bfd_check_format_matches (symtab->bfd, bfd_object, &matching))
- goto BAIL;
-
- symcount = bfd_read_minisymbols (symtab->bfd, false, (PTR) &symtab->syms, &size);
- if (symcount == 0) {
- symcount = bfd_read_minisymbols (symtab->bfd, true /* dynamic */ ,
- (PTR) &symtab->syms, &size);
- }
- if (symcount < 0)
- goto BAIL;
-
- if ((bfd_get_file_flags (symtab->bfd) & HAS_SYMS) == 0)
- goto BAIL;
-
- return 1;
-
- BAIL:
- _symtab_fini (symtab);
- return 0;
- }
-
- /* Look for an address in a section.
- * This is called via bfd_map_over_sections.
- */
- static void
- find_address_in_section (bfd *abfd,
- asection *section,
- void *data)
- {
- bfd_vma vma;
- bfd_size_type size;
- struct symbol *symbol = data;
- struct symtab *symtab = symbol->symtab;
-
- if (symbol->found)
- return;
-
- if ((bfd_section_flags (section) & SEC_ALLOC) == 0)
- return;
-
- vma = bfd_section_vma (section);
- if (symbol->pc < vma)
- return;
-
- size = bfd_section_size (section);
- if (symbol->pc >= vma + size)
- return;
-
- symbol->found = bfd_find_nearest_line (symtab->bfd, section,
- symtab->syms,
- symbol->pc - vma,
- &symbol->filename,
- &symbol->functionname,
- &symbol->line);
- }
-
- static void
- _symbol_fini (struct symbol *symbol)
- {
- }
-
- static void
- _symbol_init (struct symbol *symbol, struct symtab *symtab, bfd_vma addr)
- {
- symbol->found = false;
- symbol->symtab = symtab;
- symbol->pc = addr;
- }
-
- static void
- _symbol_print (struct symbol *symbol, char *buf, int buflen, const char *filename)
- {
- const char *name, *h;
- char path[1024];
-
- if (! symbol->found)
- return;
-
- name = symbol->functionname;
- if (name == NULL || *name == '\0')
- name = "??";
-
- if (symbol->filename != NULL)
- filename = symbol->filename;
- if (strcmp (filename, "/proc/self/exe") == 0) {
- int len = readlink ("/proc/self/exe", path, sizeof (path) - 1);
- if (len != -1) {
- path[len] = '\0';
- filename = path;
- }
- }
- h = strrchr (filename, '/');
- if (h != NULL)
- filename = h + 1;
-
- if (symbol->line) {
- snprintf (buf, buflen, "%s() [%s:%u]",
- name, filename, symbol->line);
- } else {
- snprintf (buf, buflen, "%s() [%s]", name, filename);
- }
- }
- #endif
-
- struct file_match {
- const char *file;
- ElfW(Addr) address;
- ElfW(Addr) base;
- void *hdr;
- };
-
- static int
- find_matching_file (struct dl_phdr_info *info, size_t size, void *data)
- {
- struct file_match *match = data;
- /* This code is modeled from Gfind_proc_info-lsb.c:callback() from libunwind */
- long n;
- const ElfW(Phdr) *phdr;
- ElfW(Addr) load_base = info->dlpi_addr;
-
- phdr = info->dlpi_phdr;
- for (n = info->dlpi_phnum; --n >= 0; phdr++) {
- if (phdr->p_type == PT_LOAD) {
- ElfW(Addr) vaddr = phdr->p_vaddr + load_base;
- if (match->address >= vaddr &&
- match->address < vaddr + phdr->p_memsz)
- {
- /* we found a match */
- match->file = info->dlpi_name;
- match->base = info->dlpi_addr;
- return 1;
- }
- }
- }
-
- return 0;
- }
-
- struct symbol_cache_entry {
- const void *ptr;
- struct symbol_cache_entry *hash_prev, *hash_next;
- char name[0];
- };
-
- static struct symbol_cache_entry *symbol_cache_hash[13477];
- static pthread_mutex_t symbol_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
-
- char *
- lookup_symbol (char *buf, int buflen, const void *ptr)
- {
- struct file_match match;
- #if HAVE_BFD
- struct symtab symtab;
- struct symbol symbol;
- #endif
- struct symbol_cache_entry *cache;
- int bucket;
- int len;
-
- bucket = (uintptr_t) ptr % (sizeof (symbol_cache_hash) / sizeof (symbol_cache_hash[0]));
- pthread_mutex_lock (&symbol_cache_mutex);
- for (cache = symbol_cache_hash[bucket];
- cache != NULL;
- cache = cache->hash_next)
- {
- if (cache->ptr == ptr) {
- if (cache->hash_prev != NULL) {
- cache->hash_prev->hash_next = cache->hash_next;
- if (cache->hash_next != NULL)
- cache->hash_next->hash_prev = cache->hash_prev;
- cache->hash_prev = NULL;
- cache->hash_next = symbol_cache_hash[bucket];
- symbol_cache_hash[bucket]->hash_prev = cache;
- symbol_cache_hash[bucket] = cache;
- }
-
- pthread_mutex_unlock (&symbol_cache_mutex);
- return cache->name;
- }
- }
- pthread_mutex_unlock (&symbol_cache_mutex);
-
- match.file = NULL;
- match.address = (ElfW(Addr)) ptr;
- dl_iterate_phdr (find_matching_file, &match);
-
- snprintf (buf, buflen, "0x%llx",
- (long long unsigned int) match.address);
-
- if (match.file == NULL || *match.file == '\0')
- match.file = "/proc/self/exe";
-
- #if HAVE_BFD
- if (_symtab_init (&symtab, match.file)) {
- _symbol_init (&symbol, &symtab, match.address - match.base);
- bfd_map_over_sections (symtab.bfd, find_address_in_section, &symbol);
- if (symbol.found)
- _symbol_print (&symbol, buf, buflen, match.file);
- _symbol_fini (&symbol);
-
- _symtab_fini (&symtab);
- }
- #endif
-
- len = strlen (buf);
- cache = malloc (sizeof (struct symbol_cache_entry) + len + 1);
- if (cache != NULL) {
- cache->ptr = ptr;
- memcpy (cache->name, buf, len + 1);
-
- pthread_mutex_lock (&symbol_cache_mutex);
- cache->hash_prev = NULL;
- cache->hash_next = symbol_cache_hash[bucket];
- if (symbol_cache_hash[bucket] != NULL)
- symbol_cache_hash[bucket]->hash_prev = cache;
- symbol_cache_hash[bucket] = cache;
- pthread_mutex_unlock (&symbol_cache_mutex);
- }
-
- return buf;
- }
真正需要替换的只有2处,代码片段如下:
- symcount = bfd_read_minisymbols (symtab->bfd, false, (PTR) &symtab->syms, &size);
- if (symcount == 0) {
- symcount = bfd_read_minisymbols (symtab->bfd, true /* dynamic */ ,
- (PTR) &symtab->syms, &size);
- }
- if (symcount < 0)
- goto BAIL;
执行命令后,这段内容变为:
- symcount = bfd_read_minisymbols (symtab->bfd, false, (void *) &symtab->syms, &size);
- if (symcount == 0) {
- symcount = bfd_read_minisymbols (symtab->bfd, true /* dynamic */ ,
- (void *) &symtab->syms, &size);
- }
- if (symcount < 0)
- goto BAIL;
(2)修改cairo-script-interpreter.pc.in
修改命令如下:
- sed -e "/@prefix@/a exec_prefix=@exec_prefix@" \
- -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文件原始内容如下:
- prefix=@prefix@
- libdir=@libdir@
- includedir=@includedir@
-
- Name: cairo-script-interpreter
- Description: script surface backend for cairo graphics library
- Version: @VERSION@
- Requires: cairo
- Libs: -L${libdir} -lcairo-script-interpreter
- Cflags: -I${includedir}/cairo
执行命令后,文件内容变为:
- prefix=@prefix@
- exec_prefix=@exec_prefix@
- libdir=@libdir@
- includedir=@includedir@
-
- Name: cairo-script-interpreter
- Description: script surface backend for cairo graphics library
- Version: @VERSION@
- Requires: cairo
- Libs: -L${libdir} -lcairo-script-interpreter
- Cflags: -I${includedir}/cairo