richtextbox 사용하다 문제점


현재 파일 LoadFile () 해서 copy text 

다른파일 load file() 해서 붙여넣기 


> 해당과정이 매끄럽지 못하다.

1) Loadfile의 format에 따라 될때 안될때 발생

- PlainText의 경우 현재 load된 상태에서 copy / paste 이후 다른 파일 Load해서 클립보드에 있는 내용 paste 정상동작

                         현재 load된 상태에서 copy 이후           다른 파일 load해서 클립보드에 있는 내용 paste 동작안됨.

- 하나의 파일내에서 paste는 정상동작.


2) UnicodePlainText는 정상동작.


c# naudio 로 같은 wave play 시 두번째 재생시 access error 발생


how to dispose ?



하지만 Naudio는 한 폼 안에서 한 개의 파일만 재생할 수 있었다.


using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading;

using System.Collections.Concurrent;

namespace cs_blocking_collection

{

    public class Recv

    {

        int threadCount;

        public int ThreadCount { get { return threadCount; } }

        Thread RecvT1;

        Thread RecvT2;

        private BlockingCollection<string> myBC;

        public BlockingCollection<string> RecvBC { get { return myBC; } }

        public Recv()

        {

            myBC = new BlockingCollection<string>();

            RecvT1 = new Thread(new ThreadStart(WokrerMethod));

            RecvT2 = new Thread(new ThreadStart(WokrerMethod));

            threadCount = 2;

            RecvT1.Start();

            RecvT2.Start();

        }

        private void WokrerMethod()

        {

            string s;

            while (true)

            {

                myBC.TryTake(out s, -1);

                if (s == null)

                {

                    Console.WriteLine("Error s is NULL.");

                }

                else if (s != "end")

                {

                    Console.WriteLine

                    ("Thread ID : {0}, Message : {1}", Thread.CurrentThread.ManagedThreadId, s);

                }

                else

                {

                    break;

                }

            }

        }

        public void JoinAll()

        {

            RecvT1.Join();

            RecvT2.Join();

            myBC.Dispose();

        }

    }

    public class Sender

    {

        Recv recv;

        public Sender(Recv r)

        {

            recv = r;

        }

        public void End()

        {

            for (int i = 0; i < recv.ThreadCount; i++)

            {

                recv.RecvBC.TryAdd("end", -1);

            }

            recv.JoinAll();

        }

        public void SendMessage(string s)

        {

            recv.RecvBC.TryAdd(s, -1);

        }

    }

    class Program

    {

        static void Main(string[] args)

        {

            Recv recv = new Recv();

            Sender sender = new Sender(recv);

            for (int i = 0; i < 1000; i++)

            {

                sender.SendMessage(string.Format("Send {0}", i));

            }

            Console.WriteLine("Completed sending message.");

            sender.End();

        }

    }

}

http://crystalcube.co.kr/123


 [WaveHeader.h]


#pragma once


#define WAVE_FORMAT_UNKNOWN      0X0000;
#define WAVE_FORMAT_PCM          0X0001;
#define WAVE_FORMAT_MS_ADPCM     0X0002;
#define WAVE_FORMAT_IEEE_FLOAT   0X0003;
#define WAVE_FORMAT_ALAW         0X0006;
#define WAVE_FORMAT_MULAW        0X0007;
#define WAVE_FORMAT_IMA_ADPCM    0X0011;
#define WAVE_FORMAT_YAMAHA_ADPCM 0X0016;
#define WAVE_FORMAT_GSM          0X0031;
#define WAVE_FORMAT_ITU_ADPCM    0X0040;
#define WAVE_FORMAT_MPEG         0X0050;
#define WAVE_FORMAT_EXTENSIBLE   0XFFFE;



typedef struct
{
	unsigned char ChunkID[4];    // Contains the letters "RIFF" in ASCII form
	unsigned int ChunkSize;      // This is the size of the rest of the chunk following this number
	unsigned char Format[4];     // Contains the letters "WAVE" in ASCII form
} RIFF;

//-------------------------------------------
// [Channel]
// - streo     : [left][right]
// - 3 channel : [left][right][center]
// - quad      : [front left][front right][rear left][reat right]
// - 4 channel : [left][center][right][surround]
// - 6 channel : [left center][left][center][right center][right][surround]
//-------------------------------------------
typedef struct
{
	unsigned char  ChunkID[4];    // Contains the letters "fmt " in ASCII form
	unsigned int   ChunkSize;     // 16 for PCM.  This is the size of the rest of the Subchunk which follows this number.
	unsigned short AudioFormat;   // PCM = 1
	unsigned short NumChannels;   // Mono = 1, Stereo = 2, etc.
	unsigned int   SampleRate;    // 8000, 44100, etc.
	unsigned int   AvgByteRate;   // SampleRate * NumChannels * BitsPerSample/8
	unsigned short BlockAlign;    // NumChannels * BitsPerSample/8
	unsigned short BitPerSample;  // 8 bits = 8, 16 bits = 16, etc
} FMT;


typedef struct
{
	char          ChunkID[4];    // Contains the letters "data" in ASCII form
	unsigned int  ChunkSize;     // NumSamples * NumChannels * BitsPerSample/8
} DATA;


typedef struct
{
	RIFF Riff;
	FMT	 Fmt;
	DATA Data;
} WAVE_HEADER;





    [Test.cpp]


#include <iostream>
#include "WaveHeader.h"


#define DURATION 10
#define SAMPLE_RATE 44100
#define CHANNEL 1
#define BIT_RATE 32

int main() {
	FILE * f_out;
    f_out = fopen("D:\\test.wav", "wb");

    WAVE_HEADER header;
    memcpy(header.Riff.ChunkID, "RIFF", 4);
    header.Riff.ChunkSize = DURATION * SAMPLE_RATE * CHANNEL * BIT_RATE / 8 + 36;
    memcpy(header.Riff.Format, "WAVE", 4);

    memcpy(header.Fmt.ChunkID, "fmt ", 4);
    header.Fmt.ChunkSize = 0x10;
    header.Fmt.AudioFormat = WAVE_FORMAT_PCM;
    header.Fmt.NumChannels = CHANNEL;
    header.Fmt.SampleRate = SAMPLE_RATE;
    header.Fmt.AvgByteRate = SAMPLE_RATE * CHANNEL * BIT_RATE / 8;
    header.Fmt.BlockAlign = CHANNEL * BIT_RATE / 8;
    header.Fmt.BitPerSample = BIT_RATE;

    memcpy(header.Data.ChunkID, "data", 4);
    header.Data.ChunkSize = DURATION * SAMPLE_RATE * CHANNEL * BIT_RATE / 8;

    fwrite(&header, sizeof(header), 1, f_out);

    short y[1];
    double freq = 1000;
    for(int i = 0; i < SAMPLE_RATE * DURATION * CHANNEL * BIT_RATE / 8; i++) {
        y[0] = (short)30000*sin(2 * 3.141592 * i * freq / SAMPLE_RATE); // 제임스님 코멘트에 따른 수정
        fwrite(&y[0], sizeof(short), 1, f_out);
    }

    fclose(f_out);

    

	return 0;
}


ftp backup시 file수가 너무 많은 파일 transction으로 인한 문제점(??)해소를 위한 방법으로 현재 path 에서 subfolder N-depth 이상의 folder들은 모두 tar 로 묶어서 ftp backup을 하고자 한다. N-depth 이하도 물론 tar로 묶어야함.


 

 - test.bat : test용 folder serch만 작성됨.

tar로 묵는부분은 작성되지 않음


@echo off

setlocal


::

::  init

::

set CUR_PATH=%~dp0

echo current path:%CUR_PATH%

set /a depth_cnt=0

set /a max_depth=3

set lastfolder=false




::

:: main 

::

REM FOR /L %%G IN (1,1,3) DO (

  call :dirlist

REM )

echo ######### goto end

goto :end



::--------------------------------------------------------

::-- Function section starts below here

::--------------------------------------------------------


:dirlist

dir /a:d-s /b

for /f "delims=" %%f in ('dir /a:d-s /b') do (  

  set /a depth_cnt=0  

  call :DoInSub "%%f"  

)

goto:eof








::--------------------------------------------------------

::-- Function section starts below here

::--------------------------------------------------------


:DoInSub

if %depth_cnt% equ %max_depth% (

  echo DO FINALJOB at %1

  goto:eof


if not [%1]==[] (

  set /a depth_cnt +=1

  cd %1

  echo. DO SOMETHING HERE :%~1 : %depth_cnt%

  call:dirSublist %1

 

) else (

  echo end of dirsub :%1:%depth_cnt%

)

goto:eof







::--------------------------------------------------------

::-- Function section starts below here

::--------------------------------------------------------


:dirSublist

set /a listcnt=0

for /f "delims=" %%f in ('dir /a:d /b') do (

    call :DoInSub "%%f"

    set /a listcnt +=1

)


cd ..

set /a depth_cnt -=1


if %listcnt% equ 0 (

    REM dir %1 /b

    echo DO FINALJOB at %1

)

goto:eof










REM cd %~1







::--------------------------------------------------------

::-- Function section starts below here

::--------------------------------------------------------


:myGetFunc    - passing a variable by reference

set "%~1=DosTips"

goto:eof












      

:end

endlocal


#check exe dir for searching latest user binfile and make one copy#######

for BIN_FILE in $EXE_BIN_FILES

do


##### operation "=~" is not supported by shell"sh"

#   if [[ "$BIN_FILE" =~ "$NEW_SUFFIX" ]];then

#       EXE_NEW_BIN=$BIN_FILE

#   elif [[ "$BIN_FILE" =~ "$OLD_SUFFIX" ]];then

#       EXE_OLD_BIN=$BIN_FILE

#   else


    case $BIN_FILE in

    *$NEW_SUFFIX* )

        EXE_NEW_BIN=$BIN_FILE

        ;;

    *$OLD_SUFFIX* )

        EXE_OLD_BIN=$BIN_FILE

        ;;

    *)

        if [ $CNT -eq 0 ];then

            EXE_USER_BIN=$BIN_FILE

        else

            echo "error : $EXE_DIR/$BIN_FILE is deleted"

            rm -f $EXE_DIR/$BIN_FILE

        fi


        let CNT+=1

        ;;

    esac

#   fi

done

@echo off


call setenv-local.bat







REM timake.exe C:\addpac\targets\vp230\app\build\vp230.pjt -lc

REM timake.exe /?

REM cd %dm642%\TARGET\vp230\build

REM timake.exe vp230.pjt -lc

REM timake.exe vp230.pjt VP230


REM start /d %CUR_PATH% /b %CONEMU% -cmd @%CUR_PATH%run-script.txt

REM %CONEMU% -cmd @%CUR_PATH%run-script.txt



echo %CUR_PATH%


set MY_CMD="cmd /k %CUR_PATH%your_batch_script.bat"

REM ok

REM start /d %CUR_PATH% /b %CONEMU% -cmd %MY_CMD%


REM testing

REM runas /user:Administrator "start /d %CUR_PATH% /b %CONEMU% -cmd %MY_CMD%"

REM runas /user:Administrator "\"start /d %CUR_PATH% /b %CONEMU%\""


set MY_CMD=\"cmd /k %CUR_PATH%setenv-local.bat & %CUR_PATH%your_batch_script.bat\"

REM ... error 

REM runas /env /user:Administrator "%CONEMU% -cmd %MY_CMD%"



set MY_CMD="cmd /k %CUR_PATH%setenv-local.bat & %CUR_PATH%your_batch_script.bat"

REM start /d %CUR_PATH% /b %CONEMU% -cmd %MY_CMD% -cur_console:a



set MY_CMD="cmd /k %CUR_PATH%your_batch_script.bat"

start /d %CUR_PATH% /b %CONEMU% -cmd %MY_CMD% -cur_console:a



echo "END OF RUN"

http://wiki.beyondlogic.org/index.php?title=Cross_Compiling_BusyBox_for_ARM#BusyBox


Building a minimal RootFS with Busybox, GLIBC and DropBear

BusyBox is a collection of cut down versions of common UNIX utilities compiled into a single small executable. This makes BusyBox an ideal foundation for resource constrained systems.

Prerequisites

Install the following prerequisites (assuming an Ubuntu 14.04 build machine):

apt-get install gcc-arm-linux-gnueabi
apt-get install libncurses5-dev
apt-get install gawk

BusyBox

BusyBox can be built either as a single static binary requiring no external libraries, or built requiring shared libraries such as GLIBC (default). This setting can be found under BusyBox Settings -> Build Options -> Build BusyBox as a static binary (no shared libs).

I generally choose to build BusyBox to require GLIBC as it is highly likely you will want to run additional applications that will require GLIBC sometime in the future.

wget http://busybox.net/downloads/busybox-1.24.1.tar.bz2
tar -xjf busybox-1.24.1.tar.bz2
cd busybox-1.24.1/
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig

At the menu, you can configure BusyBox options. Once configured, you can build BusyBox:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- 
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- install CONFIG_PREFIX=/home/export/rootfs

GLIBC

GLIBC is the GNU C Library and includes common system calls required by executables running on your system.

Download, build and install GLIBC:

wget http://ftp.gnu.org/gnu/libc/glibc-2.22.tar.xz
tar -xJf glibc-2.22.tar.xz
mkdir glibc-build
cd glibc-build/
../glibc-2.22/configure arm-linux-gnueabi --target=arm-linux-gnueabi --build=i686-pc-linux-gnu --prefix= --enable-add-ons
make
make install install_root=/home/export/rootfs 

Some programs may require libgcc_s.so, otherwise you will receive an error:

error while loading shared libraries: libgcc_s.so.1: cannot open shared object file: No such file or directory 

libgcc_s.so.1 can be copied over from your arm-linux-gnueabi installation:

cp /usr/lib/gcc-cross/arm-linux-gnueabi/4.7.3/libgcc_s.so.1 /home/export/rootfs/lib 

Preparing RootFS

Once BusyBox and GLIBC has been cross-compiled, you will want to create the remainder of the root file system. Start by creating the necessary directory structure:

mkdir proc sys dev etc/init.d usr/lib

Now we must mount the /proc & /sys filesystem and populate the /dev nodes. This can be done at runtime by creating a file called etc/init.d/rcS and adding:

#!bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
echo /sbin/mdev > /proc/sys/kernel/hotplug
/sbin/mdev -s

and make executable:

chmod +x etc/init.d/rcS 

You should now have a basic, yet quite functional, BusyBox root file system.

DropBear (Optional)

DropBear is a small SSH server and client and is useful to allow remote shell access to your system.

Download, build and install DropBear:


wget https://matt.ucc.asn.au/dropbear/releases/dropbear-2015.68.tar.bz2
tar -xjf dropbear-2015.68.tar.bz2
cd dropbear-2015.68
./configure --host=arm-linux-gnueabi --prefix=/ --disable-zlib CC=arm-linux-gnueabi-gcc LD=arm-linux-gnueabi-ld
make
make install DESTDIR=/home/export/rootfs

DropBear requires RSA and DSS (Digital Signature Standard) encryption keys to be generated. I normally do this on the target, but you could generate the keys on the host if you have the dropbearkey executable installed.

To generate your keys:

mkdir /etc/dropbear
dropbearkey -t dss -f /etc/dropbear/dropbear_dss_host_key  
dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key 

You will also require users and passwords to validate login credentials:

touch /etc/passwd
touch /etc/group
adduser root -u 0

Unless otherwise specified, root will be given a default home directory of /home/root. However as this doesn't exist, DropBear will close your connection immediately after successfully logging in. To address this, simply create a home directory for root:

mkdir /home /home/root

DropBear can now be started by running:

dropbear

and you should be able to remotely login to your system using the root user.

If you get an error after logging in, "Server refused to allocate pty" check you have Device Drivers > Character devices > Legacy (BSD) PTY support enabled in your kernel. (Especially applicable to Beaglebone kernels)

ldconfig

ldconfig is used to configure dynamic linker run-time bindings. It creates symbolic links and a cache to the most recent shared libraries. As you build upon your root filesystem and add additional libraries, you may need to run ldconfig.

ldconfig will search for libraries in the trusted directory /lib. Additional search paths can be added to the ld.so.conf configuration file. ldconfig looks for a configuration file in /etc/ld.so.conf and generates a warning if this cannot be found. Suppress the warning and extend the search range to include /usr/lib by:

echo /usr/lib > etc/ld.so.conf

ldconfig will also generate a cache at /etc/ld.so.cache. If this file doesn't exist, it will be automatically generated.

Finally, to update the dynamic linker run-time bindings with verbose output, execute:

ldconfig -v

Read Only Filesystems

If you are using a root file system residing on flash memory, to improve longevity it may be desirable to either mount your rootfs as read only, or to move as many of the frequently written to files (for example /var) to a temporary volatile file system stored in RAM.

The following is an expanded etc/init.d/rcS file demonstrating this.

We mount /var and /dev as tmpfs. The device nodes are generated using mdev at boot and from hotplug, hence we move these to a temp file system otherwise they could not be generated on a read only root filesystem.

#!bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t tmpfs none /var
mount -t tmpfs none /dev
echo /sbin/mdev > /proc/sys/kernel/hotplug
/sbin/mdev -s
mkdir /var/log
syslogd
dropbear

syslogd writes system messages to /var/log/messages and is something you probably don't want constantly writing to flash. After mounting /var as a temp file system, we create the /var/log directory for systemd.

원본 사이트

좋은 정보를 블로그에 올려주신 분에게 감사를...^^;

http://blog.daum.net/joell/11772014

native gdb

localhost opt  # wget ftp://ftp.jaist.ac.jp/pub/GNU/termcap/termcap-1.3.1.tar.gz
localhost opt  # tar xvzf termcap-1.3.1.tar.gz
localhost opt  # cd termcap-1.3.1
localhost termcap-1.3.1# CC=arm-linux-gcc ./configure --build=i686-linux --host=arm-linux --prefix=$PWD/build
localhost termcap-1.3.1# make && make install
localhost termcap-1.3.1# cd ..

localhost opt  # wget ftp://ftp.jaist.ac.jp/pub/GNU/gdb/gdb-6.6.tar.gz
localhost opt  # tar xvzf gdb-6.6.tar.gz 
localhost opt  # cd gdb-6.6
localhost gdb-6.6 # CFLAGS=-L/opt/termcap-1.3.1 ./configure --build=i686-linux --host=arm-linux --target=arm-linux --prefix=/nfsroot/gdb
localhost gdb-6.6 # make && make install


확인 필요
ptrace: bogus breakpoint trap 메세지가 너무 많이 나옴




gdb & gdbserver

localhost opt # wget http://core.ring.gr.jp/pub/GNU/gdb/gdb-6.6.tar.gz
localhost opt # tar xvzf gdb-6.6.tar.gz
localhost opt # cd gdb-6.6
localhost gdb-6.6 # ./configure --build=i686-linux --host=i686-linux --target=arm-linux 
--prefix=$PWD/build
localhost gdb-6.6 # 
make && make install
localhost gdb-6.6 # cp build/bin/arm-linux-gdb  /nfsroot/


localhost gdb-6.6 #
 cd gdb/gdbserver
localhost gdbserver # CC=arm-linux-gcc ./configure --build=i686-linux --host=arm-linux --target=arm-linux 
localhost gdbserver # cp gdbserver /nfsroot/




태스트

태스트 할 프로그램을 ARM용으로 컴파일 한다. 디버깅 옵션( -g )가 빠지지 않도록 주의해야 한다. 

localhost nfsroot # arm-linux-gcc -g gdb_test.c



태스트를 하기 전에 컴파일결과 만들어진 파일들을 확인해보자.

localhost nfsroot # file a.out
a.out: ELF 32-bit LSB executable, ARM, version 1, for GNU/Linux 2.0.0, dynamically linked (uses shared libs), not stripped

localhost nfsroot # file arm-linux-gdb
arm-linux-gdb: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), not stripped

localhost nfsroot # file gdbserver
gdbserver: ELF 32-bit LSB executable, ARM, version 1, for GNU/Linux 2.0.0, dynamically linked (uses shared libs), not stripped



타겟보드에서 nfs로 pc에 마운트하여 태스트를 진행한다. 주의할 점은 PC와 타겟 모두 동일한 실행파일(a.out)과 소스코드(gdb_test.c)를 가지고 있어야 한다. 

우선 minicom을 실행시키다.

localhost nfsroot # minicom



타겟보드에서 pc에  nfs 마운트한다. 타겟의 IP는 192.168.1.166, host pc의 IP는 192.168.1.167로 설정하였다.

# ifconfig eth0 192.168.1.166                                                     
# route add default gw 192.168.1.1                                                
# mount -t nfs 192.168.1.167:/nfsroot /nfsroot -o nolock,rsize=1024,wsize=1024



타겟보드에서 컴파일한 실행파일을 실행 시켜 보자.  허용되지 않은 메모리를 접근하려고 해서 segmentation fault 에러가 난 것을 확인 할 수 있다. 

# cd /nfsroot
# ./a.out
debug test
pc : [<4007a174>]    lr : [<40082994>]    Not tainted
sp : bffffdb0  ip : 4012b068  fp : 0000000a
r10: 4012cce0  r9 : 00000000  r8 : 4012b01c
r7 : 000003ff  r6 : 00000400  r5 : 00000000  r4 : 00000000
r3 : 40015001  r2 : 00000064  r1 : 40015000  r0 : 00000064
Flags: nzCv  IRQs on  FIQs on  Mode USER_32  Segment user
Control: 397F  Table: A7CB8000  DAC: 00000015
Segmentation fault



타겟보드에서 자신의 IP와 임의의 포트번호,  디버깅할 실행파일 이름을 인자로 하여 gdbserver를 실행한다.

#./gdbserver 192.168.1.166:10000 a.out
Process a.out created; pid = 61                                                 
Listening on port 10000       



PC에서 디버깅할 실행파일을 인자로 하여 gdb를 실행한다. 

localhost nfsroot # pwd
/nfsroot
localhost nfsroot # ./arm-linux-gdb  a.out
GNU gdb 6.6
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "--host=i686-linux --target=arm-linux"...
(gdb) 


우선 디버거에서 사용할 라이브러리 위치를 알려주기 위해서 툴체인의 라이브러리 상위폴더를 지정해주어야 한다. 

 (gdb) set solib-absolute-prefix /usr/local/arm-linux


pc에서 타겟보드로 연결 하자. 

(gdb) target remote 192.168.1.166:10000
Remote debugging using 192.168.1.166:10000
0x40001c80 in _start () at rtld.c:-1
-1      rtld.c: No such file or directory.
        in rtld.c


타겟보드에서 다음 메세지를 확인 할 수 있다.

Remote debugging from host 192.168.1.167


우선 실행을 시켜보자. PC에서 continue 또는 c를 입력하자

(gdb) continue
Continuing.


그리고 나서 보드에서  test라고 입력한 후 엔터를 친다. 

test
pc : [<4007a174>]    lr : [<40082994>]    Not tainted
sp : bffffdb0  ip : 4012b068  fp : 0000000a
r10: 4012cce0  r9 : 00000000  r8 : 4012b01c
r7 : 000003ff  r6 : 00000400  r5 : 00000000  r4 : 00000000
r3 : 40015001  r2 : 00000074  r1 : 40015000  r0 : 00000074
Flags: nzCv  IRQs on  FIQs on  Mode USER_32  Segment user
Control: 397F  Table: A7AC0000  DAC: 00000015


PC를 확인 해보면 Segmentation fault가 난 것을 알 수 있다. 잘못된 메모리 주소를 접근했기 때문에 난 에러이다.

Program received signal SIGSEGV, Segmentation fault.
0x4007a174 in ?? ()


gdb 명령 backtrace를 사용해보자. main함수 소스코드 라인 10줄에서 fgets함수를 호출 한 후, getline_info에서 실행이 멈춘것을 알 수 있다.  fgets의 인자로 받은 buf주소가 0x0=NULL 이어서 문제가 생긴 것이다. 

(gdb) backtrace
#0  _IO_getline_info (fp=0x4012b01c, buf=0x0, n=1023, delim=10, extract_delim=1, eof=0x0) at iogetline.c:87
#1  0x4007a05c in _IO_getline (fp=0x74, buf=0x40015000 "test\n", n=116, delim=1073827841, extract_delim=1) at iogetline.c:41
#2  0x40079274 in _IO_fgets (buf=0x0, n=1024, fp=0x4012b01c) at iofgets.c:50
#3  0x00008478 in main (argc=1, argv=0xbffffe64) at debug_test.c:10



소스코드를  확인 해 보면 10번째 라인에 fgets함수를 볼 수 있다. 인자로 buf 를 사용하고 있다 

(gdb) list debug_test.c:1
1       #include <stdio.h>
2       #include <stdlib.h>
3
4       int main( int argc, char **argv )
5       {
6               char *buf;
7
8               buf = malloc( 1<<31 );
9
10              fgets( buf, 1024, stdin );
(gdb) list +
11              printf( "%s\n", buf );
12
13              return 1;
14      }
(gdb) 


스택 프레임을 main함수로 바꾸자

(gdb) frame 3
#3  0x00008478 in main (argc=1, argv=0xbffffe64) at debug_test.c:10
10              fgets( buf, 1024, stdin );


현재 스택 프레임에 대한 정보를 자세히 보려면 

(gdb) info frame
Stack level 3, frame at 0xbffffe38:
 pc = 0x8478 in main (debug_test.c:10); saved pc 0x400381e0
 caller of frame at 0xbffffe1c
 source language c.
 Arglist at 0xbffffe34, args: argc=1, argv=0xbffffe64
 Locals at 0xbffffe34, Previous frame's sp at 0xbffffe2c
 Saved registers:
  r11 at 0xbffffe28, lr at 0xbffffe30, pc at 0xbffffe30


지역번수의 내용을 확인하면 buf의 주소가 NULL인 것을 볼 수 있다.

(gdb) info locals
buf = 0x0


아규먼트는 메인함수 호출시 사용된 것이 나온다. 

(gdb) info args
argc = 1
argv = (char **) 0xbffffe64


print명령을 사용하면 포인터 변수인 buf의 내용과 가리키는 곳의 내용을 출력할 수 있다. 역시 여기서도 가리키는 곳을 접근 할수 없다는 메세지가 나온다. 

(gdb) print buf
$1 = 0x0
(gdb) print *buf
Cannot access memory at address 0x0


현재 디버그 중인 프로그램을 중지 시키려면 kill명령을 사용하면 된다. 
타겟보드에서 실행중인 gdbserver를 중지시키게 된다.

(gdb) kill
Kill the program being debugged? (y or n) y


타겟보드에서 디버깅이 종료된 것을 확인 할 수 있다. 

Killing inferior                                                                





디버깅을 다시 시작 하기 위해 타겟보드에서 gdbserver를 다시 실행시킨다.
process id가 실행 할 때 마다 변하는 것을 볼 수 있다. 

# ./gdbserver 192.168.1.166:10000 a.out
Process a.out created; pid = 69
Listening on port 10000


PC에서도 다시 gdbserver에 접속한다.

(gdb) target remote 192.168.1.166:10000
Remote debugging using 192.168.1.166:10000
0x40001c80 in _start () at rtld.c:-1
-1      rtld.c: No such file or directory.
        in rtld.c



breakpoint를 8번째 라인으로 설정한다. 

(gdb) list debug_test.c:1
1       #include <stdio.h>
2       #include <stdlib.h>
3
4       int main( int argc, char **argv )
5       {
6               char *buf;
7
8               buf = malloc( 1<<31 );
9
10              fgets( buf, 1024, stdin );
(gdb) list +
11              printf( "%s\n", buf );
12
13              return 1;
14      }
(gdb) break 8
Breakpoint 1 at 0x8454: file debug_test.c, line 8.



(gdb) c
Continuing.

Breakpoint 1, main (argc=1, argv=0xbffffe64) at debug_test.c:8
8               buf = malloc( 1<<31 );

(gdb) print buf
$1 = 0x0
(gdb) print *buf
Cannot access memory at address 0x0



(gdb) n
10              fgets( buf, 1024, stdin );
(gdb) print buf
$2 = 0x0
(gdb) print *buf
Cannot access memory at address 0x0

출처:http://webnautes.tistory.com/entry/gdb-gdb-server-cross-compile-for-arm

cpu thread check





+ Recent posts