2010年9月23日 星期四

Backtrace的方法

‧ 版權聲明:轉載時請以超鏈結形式標明文章原始出處和作者資訊及本聲明

http://chenzhuoyou.blogbus.com/logs/35484209.html

程式在得到一個Segmentation
fault這樣的錯誤資訊毫無保留地就跳出來了,遇到這樣的問題讓人很痛苦,查找問題不亞於你N多天辛苦勞累編寫代碼的難度。那麼有沒有更好的方法可以在產生SIGSEGV信號的時候得到調試可用的資訊呢?看看下面的常式吧!



sigsegv.h

#ifndef __sigsegv_h__

#define __sigsegv_h__

#ifdef __cplusplus

extern "C" {

#endif



int setup_sigsegv();



#ifdef __cplusplus

}

#endif



#endif /* __sigsegv_h__ */



sigsegv.c



#define _GNU_SOURCE

#include <memory.h>

#include <stdlib.h>

#include <stdio.h>

#include <signal.h>

#include <ucontext.h>

#include <dlfcn.h>

#include <execinfo.h>

#ifndef NO_CPP_DEMANGLE

#include <cxxabi.h>

#endif



#if defined(REG_RIP)

# define SIGSEGV_STACK_IA64

# define REGFORMAT "%016lx"

#elif defined(REG_EIP)

# define SIGSEGV_STACK_X86

# define REGFORMAT "%08x"

#else

# define SIGSEGV_STACK_GENERIC

# define REGFORMAT "%x"

#endif



static void signal_segv(int signum, siginfo_t* info, void*ptr) {

static const char *si_codes[3] = {"", "SEGV_MAPERR", "SEGV_ACCERR"};



size_t i;

ucontext_t *ucontext = (ucontext_t*)ptr;



#if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64)

int f = 0;

Dl_info dlinfo;

void **bp = 0;

void *ip = 0;

#else

void *bt[20];

char **strings;

size_t sz;

#endif



fprintf(stderr, "Segmentation Fault!\n");

fprintf(stderr, "info.si_signo = %d\n", signum);

fprintf(stderr, "info.si_errno = %d\n", info->si_errno);

fprintf(stderr, "info.si_code = %d (%s)\n", info->si_code, si_codes[info->si_code]);

fprintf(stderr, "info.si_addr = %p\n", info->si_addr);

for(i = 0; i &lt; NGREG; i++)

fprintf(stderr, "reg[%02d] = 0x" REGFORMAT "\n", i, ucontext->uc_mcontext.gregs[i]);



#if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64)

# if defined(SIGSEGV_STACK_IA64)

ip = (void*)ucontext->uc_mcontext.gregs[REG_RIP];

bp = (void**)ucontext->uc_mcontext.gregs[REG_RBP];

# elif defined(SIGSEGV_STACK_X86)

ip = (void*)ucontext->uc_mcontext.gregs[REG_EIP];

bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP];

# endif



fprintf(stderr, "Stack trace:\n");

while(bp && ip) {

if(!dladdr(ip, &dlinfo))

break;



const char *symname = dlinfo.dli_sname;

#ifndef NO_CPP_DEMANGLE

int status;

char *tmp = __cxa_demangle(symname, NULL, 0, &status);



if(status == 0 && tmp)

symname = tmp;

#endif



fprintf(stderr, "% 2d: %p <%s+%u> (%s)\n",

++f,

ip,

symname,

(unsigned)(ip - dlinfo.dli_saddr),

dlinfo.dli_fname);



#ifndef NO_CPP_DEMANGLE

if(tmp)

free(tmp);

#endif



if(dlinfo.dli_sname && !strcmp(dlinfo.dli_sname, "main"))

break;



ip = bp[1];

bp = (void**)bp[0];

}

#else

fprintf(stderr, "Stack trace (non-dedicated):\n");

sz = backtrace(bt, 20);

strings = backtrace_symbols(bt, sz);



for(i = 0; i < sz; ++i)

fprintf(stderr, "%s\n", strings[i]);

#endif

fprintf(stderr, "End of stack trace\n");

exit (-1);

}



int setup_sigsegv() {

struct sigaction action;

memset(&action, 0, sizeof(action));

action.sa_sigaction = signal_segv;

action.sa_flags = SA_SIGINFO;

if(sigaction(SIGSEGV, &action, NULL) < 0) {

perror("sigaction");

return 0;

}



return 1;

}



#ifndef SIGSEGV_NO_AUTO_INIT

static void __attribute((constructor)) init(void) {

setup_sigsegv();

}

#endif



main.c



#include "sigsegv.h"

#include <string.h>



int die() {

char *err = NULL;

strcpy(err, "gonner");

return 0;

}



int main() {

return die();

}



下面來編譯上面的main.c程式看看將會產生什麼樣的資訊呢,不過要注意的就是如果要在你的程式裏引用sigsegv.h、sigsegv.c得到堆疊資訊的話記得加上-rdynamic
-ldl參數。



/data/codes/c/test/backtraces $ gcc -o test -rdynamic -ldl -ggdb -g sigsegv.c
main.c

/data/codes/c/test/backtraces $ ./test

Segmentation Fault!

info.si_signo = 11

info.si_errno = 0

info.si_code = 1 (SEGV_MAPERR)

info.si_addr = (nil)

reg[00] = 0x00000033

reg[01] = 0x00000000

reg[02] = 0xc010007b

reg[03] = 0x0000007b

reg[04] = 0x00000000

reg[05] = 0xb7fc8ca0

reg[06] = 0xbff04c2c

reg[07] = 0xbff04c1c

reg[08] = 0xb7f8cff4

reg[09] = 0x00000001

reg[10] = 0xbff04c50

reg[11] = 0x00000000

reg[12] = 0x0000000e

reg[13] = 0x00000006

reg[14] = 0x080489ec

reg[15] = 0x00000073

reg[16] = 0x00010282

reg[17] = 0xbff04c1c

reg[18] = 0x0000007b

Stack trace:

1: 0x80489ec <die+16> (/data/codes/c/test/backtraces/test)

2: 0x8048a16 <main+19> (/data/codes/c/test/backtraces/test)

End of stack trace

/data/codes/c/test/backtraces $



下面用gdb來看看出錯的地方左右的代碼:



/data/codes/c/test/backtraces $ gdb ./test

gdb> disassemble die+16

Dump of assembler code for function die:

0x080489dc <die+0>: push %ebp

0x080489dd <die+1>: mov %esp,%ebp

0x080489df <die+3>: sub $0x10,%esp

0x080489e2 <die+6>: movl $0x0,0xfffffffc(%ebp)

0x080489e9 <die+13>: mov 0xfffffffc(%ebp),%eax

0x080489ec <die+16>: movl $0x6e6e6f67,(%eax)

0x080489f2 <die+22>: movw $0x7265,0x4(%eax)

0x080489f8 <die+28>: movb $0x0,0x6(%eax)

0x080489fc <die+32>: mov $0x0,%eax

0x08048a01 <die+37>: leave

0x08048a02 <die+38>: ret

End of assembler dump.

gdb&gt;



也可以直接break *die+16進行調試,看看在出錯之前的堆疊情況,那麼下面我們再來看看代碼問題到底出在什麼地方了。



/data/codes/c/test/backtraces $ gdb ./test

gdb> break *die+16

Breakpoint 1 at 0x80489f2: file main.c, line 6.

gdb&gt; list *die+16

0x80489f2 is in die (main.c:6).

1 #include "sigsegv.h"

2 #include <string.h>

3

4 int die() {

5 char *err = NULL;

6 strcpy(err, "gonner");

7 return 0;

8 }

9

10 int main() {

gdb>



現在看看定位錯誤將會多麼方便,上面的調試指令中list之前break不是必須的,只是讓你可以看到break其實就已經指出了哪一行代碼導致
Segmentation fault了。如果你要發佈你的程式你一般會為了減少體積不會附帶調試資訊的(也就是不加-ggdb
-g參數),不過沒關係,你一樣可以得到上面stack-trace資訊,然後你調試之前只要加上調試資訊即可。



 

2010年9月6日 星期一

SKYPE安裝

Introduction

Skype is proprietary software that allows you to make calls over the Internet using your computer. Skype uses decentralized peer-to-peer technologies, so your calls do not go through a central server, but through distributed servers and other users. It uses its own proprietary communication protocol to achieve this. In addition, all communications are encrypted from end to end so that others cannot listen in. The Skype software is free to use, but it is not free software; the source code is proprietary and not available for modification.

General information about Skype can be found here at, Wikipedia. The official Skype website is Skype.com

SkypeEthics gives information on why some users do not use Skype.

Open alternatives Softphones using open protocols include Ekiga and Twinkle.

You need a working sound input and output configuration in order to use Skype. Most modern computers have sound output out of the box, but you need a microphone (or a headset, while you are out shopping) for the input. In order to broadcast video, you'll need a webcam.

Links to detailed information about Skype issues on Ubuntu can be found in the Resources section below.

Installing Skype

Since Ubuntu 10.04 (Lucid Lynx), Skype is part of the Canonical partner repository. To install Skype add the Canonical Partner Repository and install Skype via the Software-Center or via the Terminal.

sudo apt-get update && sudo apt-get install skype

Installing Skype on older Ubuntu versions.

Skype is not available in any Ubuntu software repository, and therefore cannot be installed with Ubuntu's package management software such as Synaptic or apt-get without adding a repository containing Skype. There is the official Skype repository: Skype Forum

You can add the Apt source like this

echo "deb http://download.skype.com/linux/repos/debian/ stable non-free #Skype" | sudo tee -a /etc/apt/sources.list > /dev/null

Import the Apt key, even it is not used, but may be useful in future:

sudo apt-key adv --keyserver pgp.mit.edu --recv-keys 0xd66b746e

Install Skype:

sudo apt-get update && sudo apt-get install skype

Using a repository, you will automatically receive future updates to the software. Please be aware that the repository is not signed, so when you try to install Skype, you will get a warning.

If you don't want to do that, or can't (for example, if you're on amd64), perhaps the easiest way to install is from the Debian (.deb) package available directly from the Skype website. The downside of this is that you won't automatically get future updates, you will have to download the new versions as they become available.

Debian Package

  1. Download Debian package from Get Skype

  2. Save and then open the file. It will open with the proper installer by default.
  3. Click on the install button.

AMD64

For Ubuntu 8.10 (Intrepid Ibex)-Ubuntu 10.04 (Lucid Lynx)

  1. Download http://www.skype.com/download/skype/linux/choose/ (choose your architecture).

  2. Install it by double-clicking the deb file and clicking "Install Package"

    Note : version 2.1 beta will work natively using PulseAudio server

    Note 2: For Ubuntu 10.04 you will need the nspluginwrapper package which is available from the multiverse. You can enable the multiverse by going to System > Administration > Software sources and enabling the "multiverse" channel.

For Ubuntu 8.04 (Hardy Heron):

  1. Download Ubuntu 64 bit Skype package

  2. Install it by double-clicking the deb file and clicking "Install package"

For Ubuntu 6.06 (Dapper Drake):

  1. Download the Debian package (http://skype.com/download/skype/linux/)

  2. Install skype: sudo dpkg -i --force-all

  3. Determine missing 32bit libs: ldd /usr/bin/skype | grep not
  4. Download the libs (the i386 version of course, hint: the package is named libqt3-mt): http://packages.ubuntu.com/

  5. mkdir ~/.32bitLibs (or use /lib32 and change last step to this directory)
  6. extract the *.deb files (dpkg-deb --extract )

  7. copy the necessary library files from the extracted packages to ~/.32bitLibs
  8. create a wrapper script: export LD_LIBRARY_PATH="/home//.32bitLibs/";skype

Running Skype

To start Skype, choose Applications->Internet->Skype. It usually takes a minute or two for Skype to get started, and you may think that nothing is happening, so be patient.

When the Skype window finally opens, sign up (if necessary) and log in to your Skype account. Test your configuration by selecting the Echo / Sound Test Service contact (if not there already, add contact echo123) and clicking on the large green button at the bottom of the Skype window. If the connection is made and you hear a voice, your sound configuration is fine. If you cannot hear a voice, see the troubleshooting section below.

Troubleshooting Skype

If you need help with troubleshooting Skype please take a look at the following page. TroubleShooting Skype

2010年9月5日 星期日

嵌入式Samba的設定檔-開一個分享檔案到/tmp

#全區域設定
[global]
#設定工作群組
workgroup = MYGROUP
#設定主機名秩
server string = Samba Server
#限制許可主機(白名單)
; hosts allow = 192.168.1. 192.168.2. 127.
#印表機設定
; load printers = yes
; printcap name = /etc/printcap
; printcap name = lpstat
; printing = bsd

#如果你要一個guest的帳號,你必需要加入/etc/passwd中否則使用者就會使用nobody
; guest account = pcguest

# 設定log檔輸出
log file = /dev/zero

# Put a capping on the size of the log files (in Kb).
max log size = 50

# Security mode. Most people will want user level security. See
# security_level.txt for details.
security = share
# Use password server option only with security = server
; password server =

# You may wish to use password encryption. Please read
# ENCRYPTION.txt, Win95.txt and WinNT.txt in the Samba documentation.
# Do not enable this option unless you have read those documents
; encrypt passwords = yes

# Using the following line enables you to customise your configuration
# on a per machine basis. The %m gets replaced with the netbios name
# of the machine that is connecting
; include = /usr/local/samba/lib/smb.conf.%m

# Most people will find that this option gives better performance.
# See speed.txt and the manual pages for details
socket options = TCP_NODELAY

# Configure Samba to use multiple interfaces
# If you have multiple network interfaces then you must list them
# here. See the man page for details.
; interfaces = 192.168.68.76/24
; interfaces = 192.168.12.2/24 192.168.13.2/24

# Browser Control Options:
# set local master to no if you don't want Samba to become a master
# browser on your network. Otherwise the normal election rules apply
; local master = no

# OS Level determines the precedence of this server in master browser
# elections. The default value should be reasonable
; os level = 33

# Domain Master specifies Samba to be the Domain Master Browser. This
# allows Samba to collate browse lists between subnets. Don't use this
# if you already have a Windows NT domain controller doing this job
; domain master = yes

# Preferred Master causes Samba to force a local browser election on startup
# and gives it a slightly higher chance of winning the election
; preferred master = yes

# Use only if you have an NT server on your network that has been
# configured at install time to be a primary domain controller.
; domain controller =

# Enable this if you want Samba to be a domain logon server for
# Windows95 workstations.
; domain logons = yes

# if you enable domain logons then you may want a per-machine or
# per user logon script
# run a specific logon batch file per workstation (machine)
; logon script = %m.bat
# run a specific logon batch file per username
; logon script = %U.bat

# Where to store roving profiles (only for Win95 and WinNT)
# %L substitutes for this servers netbios name, %U is username
# You must uncomment the [Profiles] share below
; logon path = \\%L\Profiles\%U

# Windows Internet Name Serving Support Section:
# WINS Support - Tells the NMBD component of Samba to enable it's WINS Server
; wins support = yes

# WINS Server - Tells the NMBD components of Samba to be a WINS Client
# Note: Samba can be either a WINS Server, or a WINS Client, but NOT both
; wins server = w.x.y.z

# WINS Proxy - Tells Samba to answer name resolution queries on
# behalf of a non WINS capable client, for this to work there must be
# at least one WINS Server on the network. The default is NO.
; wins proxy = yes

# DNS Proxy - tells Samba whether or not to try to resolve NetBIOS names
# via DNS nslookups. The built-in default for versions 1.9.17 is yes,
# this has been changed in version 1.9.18 to no.
dns proxy = no

#分享定議
#[homes]
# comment = Home Directories
# browseable = yes
# writable = yes

# Un-comment the following and create the netlogon directory for Domain Logons
; [netlogon]
; comment = Network Logon Service
; path = /usr/local/samba/lib/netlogon
; guest ok = yes
; writable = no
; share modes = no


# Un-comment the following to provide a specific roving profile share
# the default is to use the user's home directory
;[Profiles]
; path = /usr/local/samba/profiles
; browseable = no
; guest ok = yes


# NOTE: If you have a BSD-style print system there is no need to
# specifically define each individual printer
;[printers]
; comment = All Printers
; path = /usr/spool/samba
; browseable = no
# Set public = yes to allow user 'guest account' to print
; guest ok = no
; writable = no
; printable = yes

# This one is useful for people to share files
;[tmp]
; comment = Temporary file space
; path = /tmp
; read only = no
; public = yes

# A publicly accessible directory, but read only, except for people in
# the "staff" group
;[public]
; comment = Public Stuff
; path = /home/samba
; public = yes
; writable = yes
; printable = no
; write list = @staff

# Other examples.
#
# A private printer, usable only by fred. Spool data will be placed in fred's
# home directory. Note that fred must have write access to the spool directory,
# wherever it is.
;[fredsprn]
; comment = Fred's Printer
; valid users = fred
; path = /homes/fred
; printer = freds_printer
; public = no
; writable = no
; printable = yes

# A private directory, usable only by fred. Note that fred requires write
# access to the directory.
;[fredsdir]
; comment = Fred's Service
; path = /usr/somewhere/private
; valid users = fred
; public = no
; writable = yes
; printable = no

# a service which has a different directory for each machine that connects
# this allows you to tailor configurations to incoming machines. You could
# also use the %U option to tailor it by user name.
# The %m gets replaced with the machine name that is connecting.
;[pchome]
; comment = PC Directories
; path = /usr/pc/%m
; public = no
; writable = yes

# A publicly accessible directory, read/write to all users. Note that all files
# created in the directory by users will be owned by the default user, so
# any user with access can delete any other user's files. Obviously this
# directory must be writable by the default user. Another user could of course
# be specified, in which case all files would be owned by that user instead.
[public]
# path = /mnt/hda
# path = /mnt/mtd/
path = /tmp
public = yes
# only guest = yes
writable = yes
# printable = no

# The following two entries demonstrate how to share a directory so that two
# users can place files there that will be owned by the specific users. In this
# setup, the directory should be writable by both users and should have the
# sticky bit set on it to prevent abuse. Obviously this could be extended to
# as many users as required.
;[myshare]
; comment = Mary's and Fred's stuff
; path = /usr/somewhere/shared
; valid users = mary fred
; public = no
; writable = yes
; printable = no
; create mask = 0765


2010年9月2日 星期四

在ubuntu下執行sh shell有錯誤時可以使用下面指令改

sh在ubuntu上執行常常會發生語法錯誤的問題,
修改的方法如下

sudo dpkg-reconfigure dash

記得選否就可以了!