Using rust-gdb to debug rust (by quqi99)

Posted quqi99

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Using rust-gdb to debug rust (by quqi99)相关的知识,希望对你有一定的参考价值。

作者:张华 发表于:2022-01-29
版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明
( http://blog.csdn.net/quqi99 )

问题

这个长假了解了一下Rust, Rust会火吗?我的预测是,今后会有更多的底层软件改用Rust来开发,但是Rust也因为语法复杂让新入门的上层领域程序员很难适应,企业成本大增,这样它也就失去了更大的群众基础,那么它应该不会像曾经的Java那样如此流行。
C程序员在了解内存安全的前提下由程序员人工来保证内存安全;而Rust程序员在了解内存安全与特殊语法的前提下由编译器自动保证内存安全。
Rust的这些特殊语法是反直觉的,晦涩难学。写Rust程序需要花费大量精力在语法本身上,所以Rust可能不适用代替上层应用领域(如Java, python),但Rust对于对内存安全要求极高的底层领域(如kernel, hypervisor)还是非常有必要的,它最有可能代替的是c/c++

我们先把环境搭起来吧。

Rust是什么

如果说Go是为了方便并发程序的编写(使用了greenthread), 那么Rust解决的是内存安全和并发安全问题。并发安全通常也是由内存安全造成的。这里先说说内存安全。
那么,什么是内存安全呢?简单来说,就是不会出现内存访问错误。当有当程序访问未定义内存的时候才会产生内存错误。像C程序,我们一般看到的内存错误的情况如下:

  • 引用空指针

  • 使用未初始化内存

  • 释放后使用,也就是使用悬垂指针

  • 缓冲区溢出,比较数组越界

  • 非法释放已经释放过的指针或未分配的指针,也就是重复释放。
    产生上述问题的原因只有一个,就是都访问了未定义的内存。为了保证内存安全,Rust建立了严格的安全内存管理模型:

  • 所有权系统,每个被分配的内存都有一个独占其所有权的指针。

  • 借用和生命周期,每个变量都有其生命周期,一旦超过生命周期,变量就会被自动释放。如果是借用,则可以通过标记生命周期参数供编译器检查的方式,防止悬垂指针的情况

例如变量b指向内存的一块空间,那b就拥有对这块内存空间的使用权。

  • a = b, 相当于将b的所有权Move给a
  • b = &b, 这里使用了引用,相当于将b的所有权借用给b,此时对应Save模型,由机器通过类型系统来保证每个引用的安全。
  • a = *b, 这里使用了原生指针,将b的原生指针给b, 此时对应UnSave模型,由人来保护代码安全

又例如,对于智能指针,默认是在栈在分配空间,智能指针通过Box在堆上分配空间,程序通过引用借用对象T,这样引用在对象T的作用域结束时就会自动销毁引用,从而避免了内存问题,也不需要使用GC来造成世界暂停有利于实时系统。

因为引入了类型系统,所以也有点类型于区块链编程语言solidity自然会多出很多修饰符,例如mut (let mut b=2;), 加了mut就变量由不可变成了可变,由只读变成了可写。Rust默认不可变这样也提升了安全。

另外,除了引入内存安全模型,Rust也引入了泛型和trait(接口)来帮助抽象,这种抽象可以在编译时静态分发无开销,或者在运行时动态分发最小化开销。性能也非常高。

安装开发环境(Rust + YCM)

# Install Rust
export CARGO_HOME=/bak/rust
export RUSTUP_HOME=/bak/rust
curl https://sh.rustup.rs -sSf |sh
rustc --version

# Install YCM with vimplus - https://github.com/chxuan/vimplus
# then adjust ~/.vimrc according to own habits, eg: using scope
rm -rf ~/.vim*
git clone https://github.com/chxuan/vimplus.git ~/.vimplus
cd ~/.vimplus
./install.sh  #select to compile ycm with python2.7
./update.sh

# Custom your plugins, after modifying ~/.vimrc, then vim a file and run ",,i" to install Plugins
Plug 'fatih/vim-go'
" Conque-GDB doesn't work now
" Plug 'vim-scripts/Conque-GDB'

# Can also set the following configurations in ~/.vimrc
set colorcolumn=80
set belloff=all
" let g:ycm_server_python_interpreter = '/usr/bin/python2.7'

# then configure scope, don't use Conque-GDB
cat << EOF | tee -a ~/.vimrc
" Remove ConqueGdb part for go debug - https://michaelthessel.com/go-vim-debugging-with-gdb/

" YCM或者taglist仅能实现跳到函数定义处,但无法跳到调用函数的所有地方,故仍南要cscope
" cscope -Rbkq 创建索引,在函数处按csc即可跳到调用函数处, css搜索符号
if has("cscope")
   set cscopetag
   " set to 1 if you want the reverse search order.
   set csto=1
   " add any cscope database in current directory
   if filereadable("cscope.out")
      cs add cscope.out
   " else add the database pointed to by environment variable
   elseif \\$CSCOPE_DB !=""
      cs add \\$CSCOPE_DB
   endif

   " show msg when any other cscope db added
   set cscopeverbose
   nmap css :cs find s <C-R>=expand("<cword>")<CR><CR>
   nmap csg :cs find g <C-R>=expand("<cword>")<CR><CR>
   nmap csc :cs find c <C-R>=expand("<cword>")<CR><CR>
   nmap cst :cs find t <C-R>=expand("<cword>")<CR><CR>
   nmap cse :cs find e <C-R>=expand("<cword>")<CR><CR>
   nmap csf :cs find f <C-R>=expand("<cfile>")<CR><CR>
   nmap csi :cs find i ^<C-R>=expand("<cfile>")<CR>$<CR>
   nmap csd :cs find d <C-R>=expand("<cword>")<CR><CR>
   nmap hello :echo "hello"<CR>
endif
EOF

# Install vim + YCM + rust-analyzer
rustup component add rust-src rustc-dev llvm-tools-preview
sudo apt install build-essential cmake python3-dev libclang1 -y
cd ~/.vim/plugged/YouCompleteMe
git submodule update --init --recursive
./install.py --clang-completer --system-libclang #for c completion

cat << EOF | tee -a ~/.vimrc
set completeopt=menu,menuone                        " disable the function definition preview window
let g:ycm_complete_in_comments=1
let g:ycm_seed_identifiers_with_syntax=1
let g:ycm_collect_identifiers_from_tags_files=1
let g:ycm_goto_buffer_command='horizontal-split'    " horizontal split the window when 'goto' another location
let g:ycm_add_preview_to_completeopt=0              " (need to work with above
let g:ycm_key_invoke_completion='<C-x>'             " Set the key binding which invoke syntax completion
let g:ycm_global_ycm_extra_conf='~/.vim/ycm_extra_conf.py'
let g:ycm_rust_toolchain_root = '/path/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu'
let g:ycm_rust_src_path = '/path/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src'
map <F5> :YcmCompleter GoToDefinitionElseDeclaration<CR>
EOF

使用rust-gdb调试一个例子

cd /bak/rust/
cargo new quqi && cd quqi
cat << EOF | tee -a Cargo.toml
tokio =  version = "1.1", features=["full"] 
EOF
cat << EOF | tee src/lib.rs
#[derive(Clone, Debug)]
pub enum AnimalType 
    Cat,
    Dog,


#[derive(Clone, Debug)]
pub struct Animal 
    pub kind: AnimalType,
    pub name: String,
    pub age: usize,


#[derive(Clone, Debug)]
pub struct Person 
    pub name: String,
    pub pets: Vec<Animal>,
    pub age: usize,

EOF
cat << EOF | tee src/main.rs
use quqi::*;

fn main() 
    let animals: Vec<Animal> = vec![
        Animal 
            kind: AnimalType::Cat,
            name: "Chip".to_string(),
            age: 4,
        ,
        Animal 
            kind: AnimalType::Cat,
            name: "Nacho".to_string(),
            age: 6,
        ,
        Animal 
            kind: AnimalType::Dog,
            name: "Taco".to_string(),
            age: 2,
        ,
    ];

    get_chip(&animals);


fn get_chip(animals: &Vec<Animal>) 
    let chip = animals.get(0);
    println!("chip: :?", chip);

EOF
cargo build  #debug as default
cargo build --release
cargo run
./target/debug/quqi
rust-gdb target/debug/quqi
(gdb) b get_chip
(gdb) r
(gdb) info args
animals = 0x7fffffffd3a8
(gdb) p animals
$1 = (*mut alloc::vec::Vec<quqi::Animal, alloc::alloc::Global>) 0x7fffffffd3a8
(gdb) p *animals
$2 = Vec(size=3) = quqi::Animal kind: quqi::AnimalType::Cat, name: "Chip", age: 4,
  quqi::Animal kind: quqi::AnimalType::Cat, name: "Nacho", age: 6, quqi::Animal kind: quqi::AnimalType::Dog, name: "Taco", age: 2
(gdb) frame
#0  quqi::get_chip (animals=0x7fffffffd3a8) at src/main.rs:26
26	    let chip = animals.get(0)

Reference

[1] https://blog.csdn.net/quqi99/article/details/78272852
[2] https://blog.csdn.net/quqi99/article/details/121428987
[3] https://blog.logrocket.com/debugging-rust-apps-with-gdb/

以上是关于Using rust-gdb to debug rust (by quqi99)的主要内容,如果未能解决你的问题,请参考以下文章

Using rust-gdb to debug rust (by quqi99)

Using rust-gdb to debug rust (by quqi99)

Using qemu to debug kernel (by quqi99)

Using qemu to debug kernel (by quqi99)

Using qemu to debug kernel (by quqi99)

Unable to fit model using “lrm.fit” in R