├── .github ├── ISSUE_TEMPLATE.md └── workflows │ ├── changelog_audit.yml │ ├── lint.yml │ ├── lint_docs.yml │ ├── release.yml │ └── unit_test.yml ├── .gitignore ├── .nojekyll ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── LICENSE ├── README.md ├── _sidebar.md ├── code-debug ├── .eslintrc ├── .markdownlint.yml ├── .markdownlintignore ├── .mocharc.yml ├── .nycrc.yml ├── .prettierignore ├── .prettierrc ├── .vscodeignore ├── CHANGELOG.md ├── HACKING.md ├── README-ExtensionMarkets.md ├── cspell-dict.txt ├── cspell.json ├── images │ ├── disable-current-space-breakpoints-dark.svg │ ├── disable-current-space-breakpoints-light.svg │ ├── icon-plain.svg │ ├── icon.png │ ├── icon.svg │ ├── logMessage.gif │ ├── preview.png │ ├── remove-all-cli-breakpoints-dark.svg │ ├── remove-all-cli-breakpoints-light.svg │ ├── remove-debug-file-dark.svg │ ├── remove-debug-file-light.svg │ ├── set-border-breakpoints-dark.svg │ ├── set-border-breakpoints-light.svg │ ├── tutorial1-alt.png │ ├── tutorial1.png │ ├── tutorial2.png │ ├── update-all-spaces-breakpoints-info-dark.svg │ └── update-all-spaces-breakpoints-info-light.svg ├── package-lock.json ├── package.json ├── src │ ├── OSStateMachine.ts │ ├── backend │ │ ├── backend.ts │ │ ├── gdb_expansion.ts │ │ ├── linux │ │ │ └── console.ts │ │ ├── mi2 │ │ │ ├── mi2.ts │ │ │ ├── mi2lldb.ts │ │ │ └── mi2mago.ts │ │ └── mi_parse.ts │ ├── demo.html │ ├── frontend │ │ ├── constants.ts │ │ ├── consts.ts │ │ ├── extension.ts │ │ └── useless.html │ ├── gdb.ts │ ├── lldb.ts │ ├── mago.ts │ ├── mibase.ts │ ├── path_kind.ts │ ├── platform_specific.ts │ ├── source_file_map.ts │ ├── test │ │ └── unit │ │ │ ├── gdb_expansion.test.ts │ │ │ ├── mi_parse.test.ts │ │ │ ├── path_kind.test.ts │ │ │ ├── source_file_map.test.ts │ │ │ └── utils.test.ts │ └── utils.ts └── tsconfig.json ├── docker ├── Dockerfile ├── Makefile ├── README.md └── overview.drawio.svg ├── docs ├── assets │ └── images │ │ ├── 2024-11-29202614.png │ │ ├── 2024-12-06155429.png │ │ └── image-20241206201635589.png ├── readme.md ├── 会议记录 │ └── 会议记录_1.md ├── 周报 │ ├── record_1 │ │ ├── 20240228-具体工作.md │ │ ├── 20240327-具体工作.md │ │ ├── 20240417-具体工作.md │ │ ├── 20240431-具体工作.md │ │ ├── 20240505-具体工作.md │ │ ├── 20240515-具体工作.md │ │ ├── 20240525-具体工作.md │ │ ├── 20240601-具体工作.md │ │ ├── 20240610-具体工作.md │ │ ├── 20240615-具体工作.md │ │ ├── 20240706-具体工作.md │ │ ├── 20240715-具体工作.md │ │ ├── 20240725-具体工作.md │ │ ├── 20240729-具体工作.md │ │ ├── 20240809-具体工作.md │ │ └── 20240815-具体工作.md │ └── record_2 │ │ └── 20241206-具体工作.md └── 操作系统大赛参赛文档 │ └── 决赛一阶段文档.pdf ├── index.html ├── installation and usage ├── ebpf_launch.json ├── readme.md ├── test.sh ├── xv6_launch.json └── 硬件配置与调试.md ├── pre-record ├── 2023-01-02-rcore-Tutorial-ebpf复现文档.md ├── 2023-02-13.md ├── 2023-02-20.md ├── 2023-03-02.md ├── 2023-03-09.md ├── 2023-03-16.md ├── 2023-03-23.md ├── 2023-03-30.md ├── 2023-04-06.md ├── 2023-04-13.md ├── 2023-04-20.md ├── 2023-04-27.md ├── 2023-05-04.md ├── 2023-05-11.md ├── 2023-05-18.md ├── 2023-05-25.md ├── 2023-06-01.md ├── 2023-06-08.md ├── 2023-06-15.md ├── 2023-06-23.md ├── 2023-06-29.md ├── 2023-07-05.md ├── 2023-07-07-修正文档.pdf ├── 2023-07-09.md ├── 2023-07-12.md ├── 2023-07-13.md ├── 2023-07-15.md ├── 2023-07-16.md ├── 2023-07-19.md ├── 2023-07-20.md ├── 2023-07-23.md ├── 2023-07-24.md ├── 2023-07-26.md ├── 2023-07-27.md ├── 2023-07-28.md ├── 2023-07-29.md ├── 2023-07-30.md ├── 2023-07-31.md ├── 2023-08-01.md ├── 2023-08-02.md ├── 2023-08-04.md ├── 2023-08-06.md ├── 2023-08-10.md ├── 2023-08-14.md ├── 2023-oscomp-share-13.pdf ├── 2023S.md ├── 2023操作系统设计赛参赛经验分享-陈志扬.pptx ├── 2024-01-08.md ├── 2024-01-14.md ├── 2024-04-08.md ├── 2024-04-19.md ├── README-OSComp2023.md ├── README.md ├── Slides-August.md ├── Slides-August.pdf ├── Slides-July.pdf ├── Slides-OSATC.md ├── arch-eBPF-thoughts.md ├── diff-rCore-Tutorial-Code-2023S-kernel.diff ├── diff-rCore-Tutorial-Code-2023S-user.diff ├── ebpf-ui.md ├── ebpf-update.md ├── ebpf_vs_ptrace.md ├── image │ ├── image-20230814224042999.png │ ├── image-20230814224110164.png │ ├── image-20230814224131871.png │ ├── image-20230814224145315.png │ ├── image-20230814224207165.png │ ├── image-20230814224220270.png │ ├── image-20230814224231835.png │ ├── image-20230814224416817.png │ ├── image-20230814224424724.png │ ├── image-20230814224430651.png │ ├── image-20230814224452355.png │ ├── image-20230814224504863.png │ ├── image-20230814224510933.png │ ├── image-20230814224515641.png │ ├── image-20230814224521448.png │ ├── image-20230814224528153.png │ ├── image-20230814224534802.png │ ├── image-20230814224541472.png │ ├── image-20230814224602068.png │ ├── image-20230814224608979.png │ ├── image-20230814224617880.png │ ├── image-20230814224623546.png │ ├── image-20230814224627053.png │ ├── image-20230814224632667.png │ ├── image-20230814224643271.png │ ├── image-20230814224655298.png │ ├── image-20230814224717507.png │ ├── image-20230814224723030.png │ ├── image-20230814224730754.png │ ├── image-20230814224735588.png │ ├── image-20230814224743741.png │ ├── image-20230814224759724.png │ ├── image-20230814224806930.png │ ├── image-20230814224812301.png │ ├── image-20230814224818236.png │ ├── image-20230814224829324.png │ ├── image-20230814224834373.png │ ├── image-20230814224839246.png │ ├── image-20230814224844219.png │ ├── image-20230814224850295.png │ ├── image-20230814224856529.png │ ├── image-20230814224902769.png │ ├── image-20230814224907727.png │ ├── image-20230814224911662.png │ ├── image-20230814224916020.png │ ├── image-20230814224920706.png │ ├── image-20230814224924064.png │ ├── image-20230814224931754.png │ ├── image-20230814224942613.png │ ├── image-20230814224947204.png │ ├── image-20230814231257983.png │ ├── image-20230814231311699.png │ ├── image-20230814231318315.png │ ├── image-20230814231327685.png │ ├── image-20230814231334958.png │ ├── image-20230814231342847.png │ ├── image-20230814231358967.png │ └── image-20230814231425659.png ├── imgs │ ├── 1.png │ ├── 2.png │ ├── 3.png │ ├── 4.png │ ├── 5.png │ ├── 6.png │ ├── 7.png │ ├── 8.png │ ├── 9.png │ ├── Debug-Adapter-Drawio.png │ ├── DebugAdapter.png │ ├── arch-220909.png │ ├── arch-august.png │ ├── arch-with-ebpf.png │ ├── arch.png │ ├── async-msg.drawio │ ├── border.png │ ├── brk.png │ ├── browser_os_multiple_tab.png │ ├── browser_simplehttp_multiple_tab_bug.png │ ├── code-debug UI.png │ ├── coredebugger-screenshot-bootstrap-mid.png │ ├── debug-arch1.png │ ├── framework.png │ ├── gdb-debug-method1.png │ ├── gdb-debug-method2.png │ ├── gdb-debug-method3.png │ ├── gdb-embedded-arm.png │ ├── gdb-traditional.png │ ├── gdbserver-embedded.png │ ├── messageFlow.png │ ├── new-Coredebugger-APIs.png │ ├── pre-2022-07-24.mp4 │ ├── pre.mp4 │ ├── pre_with_sub.mp4 │ ├── text.png │ ├── vscode-button.png │ └── vscode-scope.png ├── memory-read-write.md ├── mid.md ├── multiple_stubs.md ├── new-code-debug-8-3.drawio ├── oscomp-final.pptx ├── oscomp_share17_rust_debugger.pptx ├── pcb_name.md ├── port-to-hardware.md ├── port.md ├── rCore-mod-old.diff ├── rCore-mod-older.md ├── rCore-mod.diff ├── rcore学习文档.md ├── thesis-2023-july.md ├── thesis-outline.md ├── thesis.md ├── treeview.md ├── 开发记录和知识库.pdf ├── 最终报告.pdf ├── 泉城集中开发-陈志扬.pdf ├── 泉城集中开发-陈志扬.pptx ├── 演示视频.mp4 ├── 硬件开发文档.md ├── 答辩PPT.pptx ├── 调试器测试文档.md └── 陈志扬-OSATC-20230325-1807.pdf └── 说明文档.md /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | If submitting a bug please make sure 2 | 3 | - [ ] If you are using gdb 4 | - [ ] `gdb --version` >= 7.7.1 5 | - [ ] it works on the command line with `gdb` 6 | - [ ] `cwd` and `target` are properly set 7 | - [ ] If you are using lldb 8 | - [ ] `lldb --version` >= 3.7.1 9 | - [ ] it works on the command line with `lldb-mi` 10 | - [ ] `cwd` and `target` are properly set 11 | 12 | Screenshots are helpful but not required -------------------------------------------------------------------------------- /.github/workflows/changelog_audit.yml: -------------------------------------------------------------------------------- 1 | name: Changelog Audit 2 | defaults: 3 | run: 4 | working-directory: code-debug # Not working 5 | on: 6 | push: 7 | paths: 8 | - ./code-debug/CHANGELOG.md 9 | pull_request: 10 | paths: 11 | - ./code-debug/CHANGELOG.md 12 | jobs: 13 | # Linting, stylechecking and spellchecking are covered by the general document 14 | # linting job, so this only checks that the changelog is conformant with the 15 | # "Keep a Changelog" format. 16 | changelog_audit: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v3 21 | 22 | - name: Validate Changelog 23 | uses: mindsers/changelog-reader-action@v2 24 | with: 25 | validation_level: error 26 | path: ./code-debug/CHANGELOG.md 27 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint Project 2 | defaults: 3 | run: 4 | working-directory: code-debug 5 | on: 6 | push: 7 | pull_request: 8 | jobs: 9 | lint: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v3 14 | 15 | - name: Install Node.js 16 | uses: actions/setup-node@v3 17 | with: 18 | node-version: 16.x 19 | 20 | - name: Install Module Dependencies 21 | run: npm clean-install --omit=optional 22 | 23 | - name: Lint Project 24 | run: npm run lint 25 | -------------------------------------------------------------------------------- /.github/workflows/lint_docs.yml: -------------------------------------------------------------------------------- 1 | name: Lint Project Documentation (Temporarily closed, does nothing) 2 | defaults: 3 | run: 4 | working-directory: code-debug 5 | on: 6 | push: 7 | paths: 8 | - '**.md' 9 | pull_request: 10 | paths: 11 | - '**.md' 12 | jobs: 13 | lint_docs: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v3 18 | 19 | - name: Ignore lint_docs 20 | run: echo "lint_docs causes too much trouble, so we closed it temporarily." 21 | 22 | # - name: Install Node.js 23 | # uses: actions/setup-node@v3 24 | # with: 25 | # node-version: 16.x 26 | 27 | # - name: Install Module Dependencies 28 | # run: npm clean-install --omit=optional 29 | 30 | # - name: Stylecheck Project Documentation 31 | # run: npm run prettier-check-docs 32 | 33 | # - name: Lint Project Documentation 34 | # run: npm run lint-docs 35 | 36 | # - name: Lint Documentation Links 37 | # run: npm run link-check 38 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | defaults: 3 | run: 4 | working-directory: code-debug 5 | on: 6 | release: 7 | types: [published] 8 | 9 | jobs: 10 | release: 11 | strategy: 12 | matrix: 13 | os: ['ubuntu-latest'] 14 | node-version: ['18.x'] 15 | runs-on: ${{ matrix.os }} 16 | steps: 17 | # 18 | # Basic Setup 19 | # 20 | - name: Checkout 21 | uses: actions/checkout@v3 22 | 23 | - name: Install Node.js ${{ matrix.node-version }} 24 | uses: actions/setup-node@v3 25 | with: 26 | node-version: ${{ matrix.node-version }} 27 | 28 | # - name: Install Module Dependencies 29 | # run: npm clean-install --omit=optional 30 | - name: Install Dependencies 31 | run: npm install 32 | 33 | # 34 | # Package and Upload Extension 35 | # 36 | # NOTE: 37 | # The "vscode:prepublish" script in package.json will be executed to compile the extension 38 | # prior to packaging. 39 | # 40 | - name: Package Extension into .vsix file 41 | id: asset 42 | shell: bash 43 | run: > 44 | npx vsce package; 45 | echo "vsix_path=$(ls *.vsix)" >> $GITHUB_ENV 46 | 47 | - name: Upload .vsix file to Github as release asset 48 | uses: actions/upload-release-asset@v1 49 | env: 50 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 51 | with: 52 | upload_url: ${{ github.event.release.upload_url }} 53 | asset_path: code-debug/${{ env.vsix_path }} 54 | asset_name: ${{ env.vsix_path }} 55 | asset_content_type: application/zip 56 | 57 | # 58 | # Publish Extension 59 | # 60 | - name: Publish to VSCode Extension Marketplace 61 | env: 62 | VSCE_PAT: ${{ secrets.VS_MARKETPLACE_TOKEN }} 63 | run: npx vsce publish --packagePath ${{ env.vsix_path }} 64 | 65 | - name: Publish to Open VSX Registry 66 | env: 67 | OVSX_PAT: ${{ secrets.OPEN_VSX_TOKEN }} 68 | run: npx ovsx publish ${{ env.vsix_path }} 69 | -------------------------------------------------------------------------------- /.github/workflows/unit_test.yml: -------------------------------------------------------------------------------- 1 | name: Unit Test Project 2 | defaults: 3 | run: 4 | working-directory: code-debug 5 | on: 6 | push: 7 | pull_request: 8 | jobs: 9 | unit_test: 10 | strategy: 11 | matrix: 12 | os: [ubuntu-latest, windows-latest, macos-latest] 13 | runs-on: ${{ matrix.os }} 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v3 17 | 18 | - name: Install Node.js 19 | uses: actions/setup-node@v3 20 | with: 21 | node-version: 16.x 22 | 23 | - name: Install Module Dependencies 24 | run: npm clean-install --omit=optional 25 | 26 | - name: Test Project 27 | run: npm test 28 | 29 | - name: Generate Test Coverage 30 | run: npm run coverage 31 | 32 | - name: Report Test Coverage 33 | uses: codecov/codecov-action@v3 34 | with: 35 | directory: ./coverage 36 | verbose: true 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | coverage 3 | node_modules 4 | *.vsix 5 | .nyc_output 6 | .vscode-test 7 | .secrets -------------------------------------------------------------------------------- /.nojekyll: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | { 3 | "version": "0.1.0", 4 | "configurations": [ 5 | { 6 | "name": "Launch Extension", 7 | "type": "extensionHost", 8 | "request": "launch", 9 | "runtimeExecutable": "${execPath}", 10 | "args": ["--extensionDevelopmentPath=${config:code-debug.sourceCodePath}" ], 11 | "stopOnEntry": false, 12 | "sourceMaps": true, 13 | "outFiles": [ 14 | "${config:code-debug.sourceCodePath}/out/**/*.js" 15 | ], 16 | "preLaunchTask": "compile" 17 | }, 18 | { 19 | "name": "code-debug server", 20 | "type": "node", 21 | "request": "launch", 22 | "runtimeArgs": [ "--nolazy" ], 23 | "program": "${config:code-debug.sourceCodePath}/src/gdb.ts", 24 | "stopOnEntry": false, 25 | "args": [ "--server=4711" ], 26 | "sourceMaps": true, 27 | "outFiles": [ 28 | "${config:code-debug.sourceCodePath}/out/**/*.js" 29 | ], 30 | "cwd": "${config:code-debug.sourceCodePath}", 31 | "preLaunchTask": "compile" 32 | }, 33 | { 34 | "name": "Launch Tests", 35 | "type": "extensionHost", 36 | "request": "launch", 37 | "runtimeExecutable": "${execPath}", 38 | "args": [ 39 | "--extensionDevelopmentPath=${config:code-debug.sourceCodePath}", 40 | "--extensionTestsPath=${config:code-debug.sourceCodePath}/out/src/test/suite/index" 41 | ], 42 | "stopOnEntry": false, 43 | "sourceMaps": true, 44 | "outFiles": [ 45 | "${config:code-debug.sourceCodePath}/out/**/*.js" 46 | ], 47 | "preLaunchTask": "compile" 48 | } 49 | ], 50 | "compounds": [ 51 | { 52 | "name": "Extension Debugging (Extension + Debug Server)", 53 | "configurations": ["Launch Extension", "code-debug server"] 54 | }, 55 | ] 56 | } 57 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "editor.insertSpaces": false, 4 | "[markdown]": { 5 | "editor.defaultFormatter": "esbenp.prettier-vscode", 6 | "editor.formatOnSave": true, 7 | "editor.rulers": [80], 8 | "editor.wordWrap": "bounded", 9 | "editor.wordWrapColumn": 80 10 | }, 11 | "files.associations": { 12 | // VSCode defaults these to Markdown instead of ignore files 13 | ".markdownlintignore": "ignore", 14 | ".prettierignore": "ignore" 15 | }, 16 | "files.exclude": { 17 | "out": false // set this to true to hide the "out" folder with the compiled JS files 18 | }, 19 | "mochaExplorer.timeout": 999999, // Set large so debugging doesn't trigger mocha timeout 20 | "search.exclude": { 21 | "**/node_modules": false, 22 | "${config:code-debug.sourceCodePath}/out": true, 23 | }, 24 | "testExplorer.useNativeTesting": true, // Use VSCode Native Test Explorer 25 | "typescript.tsdk": "${config:code-debug.sourceCodePath}/node_modules/typescript/lib", // we want to use the TS server from our node_modules folder to control its version 26 | "code-debug.sourceCodePath":"${workspaceRoot}/code-debug" 27 | } 28 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // Available variables which can be used inside of strings. 2 | // ${workspaceRoot}: the root folder of the team 3 | // ${file}: the current opened file 4 | // ${fileBasename}: the current opened file's basename 5 | // ${fileDirname}: the current opened file's dirname 6 | // ${fileExtname}: the current opened file's extension 7 | // ${cwd}: the current working directory of the spawned process 8 | { 9 | "version": "2.0.0", 10 | "tasks": [ 11 | { 12 | // A task runner that calls a custom npm script that compiles the extension. 13 | "label": "compile", 14 | // Run in a shell so "npm" command is properly resolved to "npm.cmd" on Windows systems. 15 | "type": "shell", 16 | // we want to run npm 17 | "command": "npm", 18 | // we run the custom script "compile" as defined in package.json 19 | "args": [ 20 | "run", 21 | "compile", 22 | "--loglevel", 23 | "silent" 24 | ], 25 | // The tsc compiler is started in background mode 26 | "isBackground": true, 27 | // use the standard tsc in watch mode problem matcher to find compile problems in the output. 28 | "problemMatcher": "$tsc-watch", 29 | // that's our build 30 | "group":{ 31 | "kind": "build", 32 | "isDefault": true 33 | }, 34 | "options": { 35 | "cwd": "${config:code-debug.sourceCodePath}" 36 | }, 37 | }, 38 | { 39 | "label": "npm:lint", 40 | "detail": "Lint (ESLint) Project", 41 | "type": "shell", 42 | "command": "npm", 43 | "group": "build", 44 | "args": ["run", "lint"], 45 | "problemMatcher": "$eslint-compact", 46 | "options": { 47 | "cwd": "${config:code-debug.sourceCodePath}" 48 | }, 49 | }, 50 | { 51 | "label": "npm:lint-fix", 52 | "detail": "Lint Project with Auto-fix", 53 | "type": "shell", 54 | "command": "npm", 55 | "group": "build", 56 | "args": ["run", "lint-and-fix"], 57 | "problemMatcher": "$eslint-compact", 58 | "options": { 59 | "cwd": "${config:code-debug.sourceCodePath}" 60 | }, 61 | }, 62 | // Ctrl + Shift + P (Command Palette), then select "Tasks: Run Test Task" and select "npm:test" 63 | { 64 | "label": "npm:test", 65 | "detail": "Run Project Tests", 66 | "type": "shell", 67 | "command": "npm", 68 | "group": { 69 | "kind": "test", 70 | "isDefault": true 71 | }, 72 | "args": ["test"], 73 | "options": { 74 | "cwd": "${config:code-debug.sourceCodePath}" 75 | }, 76 | }, 77 | { 78 | "label": "npm:coverage", 79 | "detail": "Run Test Coverage Report", 80 | "type": "shell", 81 | "command": "npm", 82 | "group": "test", 83 | "args": ["run", "coverage"], 84 | "options": { 85 | "cwd": "${config:code-debug.sourceCodePath}" 86 | }, 87 | }, 88 | { 89 | "label": "npm:lint-docs", 90 | "detail": "Lint Project Documentation", 91 | "type": "shell", 92 | "command": "npm", 93 | "group": "build", 94 | "args": ["run", "lint-docs"], 95 | "problemMatcher": "$markdownlint", 96 | "options": { 97 | "cwd": "${config:code-debug.sourceCodePath}" 98 | }, 99 | }, 100 | { 101 | "label": "npm:link-check", 102 | "detail": "Link Check Project Documentation", 103 | "type": "shell", 104 | "command": "npm", 105 | "group": "build", 106 | "args": ["run", "link-check"], 107 | "options": { 108 | "cwd": "${config:code-debug.sourceCodePath}" 109 | }, 110 | }, 111 | { 112 | "label": "npm:spellcheck-docs", 113 | "detail": "Spellcheck Project Documentation", 114 | "type": "shell", 115 | "command": "npm", 116 | "group": "build", 117 | "args": ["run", "spellcheck-docs"], 118 | "problemMatcher": { 119 | "fileLocation": "absolute", 120 | "owner": "spellcheck-docs", 121 | "pattern": { 122 | "regexp": "^(.+)?:(\\d+):(\\d+) - (.+)$", 123 | "file": 1, 124 | "line": 2, 125 | "column": 3, 126 | "message": 4 127 | }, 128 | "severity": "info" 129 | }, 130 | "options": { 131 | "cwd": "${config:code-debug.sourceCodePath}" 132 | }, 133 | }, 134 | { 135 | "label": "npm:prettier-write-docs", 136 | "detail": "Reformat Project Documentation", 137 | "type": "shell", 138 | "command": "npm", 139 | "group": "build", 140 | "args": ["run", "prettier-write-docs"], 141 | "options": { 142 | "cwd": "${config:code-debug.sourceCodePath}" 143 | }, 144 | } 145 | ] 146 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Proj158-支持Rust语言的源代码级内核调试工具 2 | 3 | 本文档使用docsify渲染完成,部署于[Github Pages](https://chenzhiy2001.github.io/code-debug/#/) 。点击即可查看该项目的介绍文档。 4 | -------------------------------------------------------------------------------- /_sidebar.md: -------------------------------------------------------------------------------- 1 | * [项目介绍](./说明文档.md) 2 | 3 | * [记录文档](./docs/readme.md) 4 | 5 | * [安装和使用方法](./installation%20and%20usage/readme.md) 6 | 7 | -------------------------------------------------------------------------------- /code-debug/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "node": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/eslint-recommended", 9 | // "plugin:@typescript-eslint/recommended-requiring-type-checking", 10 | "plugin:@typescript-eslint/recommended" 11 | ], 12 | "parser": "@typescript-eslint/parser", 13 | "parserOptions": { 14 | "ecmaVersion": 6, 15 | "project": "./tsconfig.json", 16 | "sourceType": "module" 17 | }, 18 | "plugins": [ 19 | "eslint-plugin-deprecation", 20 | "eslint-plugin-no-null", 21 | "@typescript-eslint" 22 | ], 23 | "root": true, 24 | "rules": { 25 | // Configure additional checks 26 | "comma-spacing": "error", 27 | "deprecation/deprecation": "error", 28 | "no-null/no-null": "error", 29 | "eol-last": "error", 30 | "indent": ["error", "tab", {"SwitchCase": 1}], 31 | // "no-console": "error", 32 | "no-trailing-spaces": "error", 33 | "prefer-const": ["error", {"ignoreReadBeforeAssign": true}], 34 | "semi": "error", 35 | "space-infix-ops": "error", 36 | "@typescript-eslint/ban-tslint-comment": "error", 37 | 38 | // Disable some recommended checks (until we can address them) 39 | "no-cond-assign": "off", 40 | "no-fallthrough": "off", 41 | "no-prototype-builtins": "off", 42 | "no-useless-escape": "off", 43 | "prefer-spread": "off", 44 | "@typescript-eslint/ban-types": "off", 45 | "@typescript-eslint/no-explicit-any": "off", 46 | "@typescript-eslint/no-inferrable-types": "off", 47 | "@typescript-eslint/no-unused-vars": "off" 48 | } 49 | } -------------------------------------------------------------------------------- /code-debug/.markdownlint.yml: -------------------------------------------------------------------------------- 1 | default: true 2 | extends: null 3 | # Don't allow any trailing whitespace. 4 | MD009: 5 | br_spaces: 0 6 | strict: true 7 | # Let Prettier handle line length and wrapping, since the 8 | # results generated by Prettier are not necessarily consistent 9 | # with what Markdownlint is expecting, especially for links. 10 | MD013: false 11 | MD034: false 12 | MD041: false 13 | MD026: false -------------------------------------------------------------------------------- /code-debug/.markdownlintignore: -------------------------------------------------------------------------------- 1 | # Temporarily ignored until they can be updated to abide by the lint rules. 2 | README.md 3 | 4 | # Don't lint markdown belonging to dependency modules. 5 | node_modules 6 | -------------------------------------------------------------------------------- /code-debug/.mocharc.yml: -------------------------------------------------------------------------------- 1 | color: true 2 | recursive: true 3 | require: "ts-node/register" 4 | spec: 5 | - "**/*.test.ts" 6 | ui: "tdd" 7 | -------------------------------------------------------------------------------- /code-debug/.nycrc.yml: -------------------------------------------------------------------------------- 1 | extends: "@istanbuljs/nyc-config-typescript" 2 | all: true 3 | reporter: 4 | - text 5 | - lcovonly 6 | -------------------------------------------------------------------------------- /code-debug/.prettierignore: -------------------------------------------------------------------------------- 1 | # Temporarily ignored until they can be updated to abide by the style rules. 2 | README.md 3 | 4 | **/.github 5 | **/.vscode-test 6 | node_modules -------------------------------------------------------------------------------- /code-debug/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "proseWrap": "always", 3 | "tabWidth": 2, 4 | "useTabs": true, 5 | "semi": true, 6 | "arrowParens": "always", 7 | "singleQuote": false, 8 | "endOfLine": "lf", 9 | "printWidth": 100 10 | } -------------------------------------------------------------------------------- /code-debug/.vscodeignore: -------------------------------------------------------------------------------- 1 | # List of paths and files to exclude from the packaged extension. 2 | .github/** 3 | .nyc_output/** 4 | .vscode/** 5 | coverage/** 6 | typings/** 7 | node_modules/**/build 8 | out/src/test/** 9 | test/** 10 | src/** 11 | **/*.map 12 | docs/** 13 | .gitignore 14 | .markdownlintignore 15 | .markdownlint.yml 16 | .mocharc.yml 17 | .nycrc.yml 18 | .prettierignore 19 | .prettierrc 20 | .secrets 21 | cspell.json 22 | cspell-dict.txt 23 | HACKING.md 24 | tsconfig.json 25 | vsc-extension-quickstart.md 26 | 演示视频.mp4 27 | 最终报告.pdf 28 | -------------------------------------------------------------------------------- /code-debug/cspell-dict.txt: -------------------------------------------------------------------------------- 1 | Codecov 2 | GDB 3 | gdbserver 4 | LLDB 5 | Microcontroller 6 | PID 7 | POSIX 8 | PPA 9 | prepended 10 | TCP 11 | theia 12 | UI 13 | VM 14 | VSIX 15 | VSX 16 | watchpoints 17 | Wireshark 18 | WSL 19 | -------------------------------------------------------------------------------- /code-debug/cspell.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2", 3 | "language": "en", 4 | "enabledLanguageIds": [ 5 | "markdown" 6 | ], 7 | "languageSettings": [ 8 | { 9 | "languageId": "markdown", 10 | "ignoreRegExpList": [ 11 | // don't spellcheck inside code fences 12 | "/```(?:.|\\n)+?^\\s*```/m", 13 | // don't spellcheck inside code quoting 14 | "/(? 3 | 5 | -------------------------------------------------------------------------------- /code-debug/images/disable-current-space-breakpoints-light.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | -------------------------------------------------------------------------------- /code-debug/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/code-debug/images/icon.png -------------------------------------------------------------------------------- /code-debug/images/logMessage.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/code-debug/images/logMessage.gif -------------------------------------------------------------------------------- /code-debug/images/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/code-debug/images/preview.png -------------------------------------------------------------------------------- /code-debug/images/remove-all-cli-breakpoints-dark.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | -------------------------------------------------------------------------------- /code-debug/images/remove-all-cli-breakpoints-light.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | -------------------------------------------------------------------------------- /code-debug/images/remove-debug-file-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /code-debug/images/remove-debug-file-light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /code-debug/images/set-border-breakpoints-dark.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /code-debug/images/set-border-breakpoints-light.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /code-debug/images/tutorial1-alt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/code-debug/images/tutorial1-alt.png -------------------------------------------------------------------------------- /code-debug/images/tutorial1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/code-debug/images/tutorial1.png -------------------------------------------------------------------------------- /code-debug/images/tutorial2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/code-debug/images/tutorial2.png -------------------------------------------------------------------------------- /code-debug/images/update-all-spaces-breakpoints-info-dark.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | -------------------------------------------------------------------------------- /code-debug/images/update-all-spaces-breakpoints-info-light.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | -------------------------------------------------------------------------------- /code-debug/src/backend/linux/console.ts: -------------------------------------------------------------------------------- 1 | import * as ChildProcess from "child_process"; 2 | import * as fs from "fs"; 3 | 4 | export function spawnTerminalEmulator(preferedEmulator: string): Thenable { 5 | return new Promise((resolve, reject) => { 6 | const ttyFileOutput = 7 | "/tmp/vscode-gdb-tty-0" + Math.floor(Math.random() * 100000000).toString(36); 8 | ChildProcess.spawn(preferedEmulator || "x-terminal-emulator", [ 9 | "-e", 10 | 'sh -c "tty > ' + ttyFileOutput + ' && sleep 4294967294"', 11 | ]); 12 | let it = 0; 13 | const interval = setInterval(() => { 14 | if (fs.existsSync(ttyFileOutput)) { 15 | clearInterval(interval); 16 | const tty = fs.readFileSync(ttyFileOutput).toString("utf8"); 17 | fs.unlinkSync(ttyFileOutput); 18 | return resolve(tty); 19 | } 20 | it++; 21 | if (it > 500) reject(); 22 | }, 10); 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /code-debug/src/backend/mi2/mi2lldb.ts: -------------------------------------------------------------------------------- 1 | import { MI2, escape } from "./mi2"; 2 | import { Breakpoint } from "../backend"; 3 | import * as ChildProcess from "child_process"; 4 | import * as path from "path"; 5 | 6 | export class MI2_LLDB extends MI2 { 7 | protected override initCommands(target: string, cwd: string, attach: boolean = false) { 8 | // We need to account for the possibility of the path type used by the debugger being different 9 | // than the path type where the extension is running (e.g., SSH from Linux to Windows machine). 10 | // Since the CWD is expected to be an absolute path in the debugger's environment, we can test 11 | // that to determine the path type used by the debugger and use the result of that test to 12 | // select the correct API to check whether the target path is an absolute path. 13 | const debuggerPath = path.posix.isAbsolute(cwd) ? path.posix : path.win32; 14 | 15 | if (!debuggerPath.isAbsolute(target)) 16 | target = debuggerPath.join(cwd, target); 17 | 18 | const cmds = [ 19 | this.sendCommand("gdb-set target-async on"), 20 | new Promise(resolve => { 21 | this.sendCommand("list-features").then(done => { 22 | this.features = done.result("features"); 23 | resolve(undefined); 24 | }, err => { 25 | this.features = []; 26 | resolve(undefined); 27 | }); 28 | }) 29 | ]; 30 | if (!attach) 31 | cmds.push(this.sendCommand("file-exec-and-symbols \"" + escape(target) + "\"")); 32 | for (const cmd of this.extraCommands) { 33 | cmds.push(this.sendCliCommand(cmd)); 34 | } 35 | return cmds; 36 | } 37 | 38 | override attach(cwd: string, executable: string, target: string, autorun: string[]): Thenable { 39 | return new Promise((resolve, reject) => { 40 | const args = this.preargs.concat(this.extraargs || []); 41 | this.process = ChildProcess.spawn(this.application, args, { cwd: cwd, env: this.procEnv }); 42 | this.process.stdout.on("data", this.stdout.bind(this)); 43 | this.process.stderr.on("data", this.stderr.bind(this)); 44 | this.process.on("exit", () => this.emit("quit")); 45 | this.process.on("error", err => this.emit("launcherror", err)); 46 | const promises = this.initCommands(target, cwd, true); 47 | promises.push(this.sendCommand("file-exec-and-symbols \"" + escape(executable) + "\"")); 48 | promises.push(this.sendCommand("target-attach " + target)); 49 | promises.push(...autorun.map(value => { return this.sendUserInput(value); })); 50 | Promise.all(promises).then(() => { 51 | this.emit("debug-ready"); 52 | resolve(undefined); 53 | }, reject); 54 | }); 55 | } 56 | 57 | override setBreakPointCondition(bkptNum: number, condition: string): Thenable { 58 | return this.sendCommand("break-condition " + bkptNum + " \"" + escape(condition) + "\" 1"); 59 | } 60 | 61 | override goto(filename: string, line: number): Thenable { 62 | return new Promise((resolve, reject) => { 63 | // LLDB parses the file differently than GDB... 64 | // GDB doesn't allow quoting only the file but only the whole argument 65 | // LLDB doesn't allow quoting the whole argument but rather only the file 66 | const target: string = (filename ? '"' + escape(filename) + '":' : "") + line; 67 | this.sendCliCommand("jump " + target).then(() => { 68 | this.emit("step-other", undefined); 69 | resolve(true); 70 | }, reject); 71 | }); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /code-debug/src/backend/mi2/mi2mago.ts: -------------------------------------------------------------------------------- 1 | import { MI2_LLDB } from "./mi2lldb"; 2 | import { Stack } from "../backend"; 3 | import { MINode } from "../mi_parse"; 4 | 5 | export class MI2_Mago extends MI2_LLDB { 6 | override getStack(startFrame: number, maxLevels: number, thread: number): Promise { 7 | return new Promise((resolve, reject) => { 8 | const command = "stack-list-frames"; 9 | this.sendCommand(command).then((result) => { 10 | const stack = result.resultRecords.results; 11 | const ret: Stack[] = []; 12 | const remaining: any = []; 13 | const addToStack = (element: any) => { 14 | const level = MINode.valueOf(element, "frame.level"); 15 | const addr = MINode.valueOf(element, "frame.addr"); 16 | const func = MINode.valueOf(element, "frame.func"); 17 | const filename = MINode.valueOf(element, "file"); 18 | const file = MINode.valueOf(element, "fullname"); 19 | let line = 0; 20 | const lnstr = MINode.valueOf(element, "line"); 21 | if (lnstr) 22 | line = parseInt(lnstr); 23 | const from = parseInt(MINode.valueOf(element, "from")); 24 | ret.push({ 25 | address: addr, 26 | fileName: filename || "", 27 | file: file || "", 28 | function: func || from || "", 29 | level: level, 30 | line: line 31 | }); 32 | }; 33 | stack.forEach(element => { 34 | if (element) 35 | if (element[0] == "stack") { 36 | addToStack(element[1]); 37 | } else remaining.push(element); 38 | }); 39 | if (remaining.length) 40 | addToStack(remaining); 41 | resolve(ret); 42 | }, reject); 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /code-debug/src/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cat Coding 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 |
15 |
16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 |

privilege:

loading

24 |

pc:

loading

25 |

SBI:

loading

26 |
27 |
28 | 29 | 76 | 77 | -------------------------------------------------------------------------------- /code-debug/src/frontend/constants.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/code-debug/src/frontend/constants.ts -------------------------------------------------------------------------------- /code-debug/src/frontend/consts.ts: -------------------------------------------------------------------------------- 1 | export const RISCV_REG_NAMES = [ 2 | "zero", 3 | "ra", 4 | "sp", 5 | "gp", 6 | "tp", 7 | "t0", 8 | "t1", 9 | "t2", 10 | "fp", 11 | "s1", 12 | "a0", 13 | "a1", 14 | "a2", 15 | "a3", 16 | "a4", 17 | "a5", 18 | "a6", 19 | "a7", 20 | "s2", 21 | "s3", 22 | "s4", 23 | "s5", 24 | "s6", 25 | "s7", 26 | "s8", 27 | "s9", 28 | "s10", 29 | "s11", 30 | "t3", 31 | "t4", 32 | "t5", 33 | "t6", 34 | "pc", 35 | "ft0", 36 | "ft1", 37 | "ft2", 38 | "ft3", 39 | "ft4", 40 | "ft5", 41 | "ft6", 42 | "ft7", 43 | "fs0", 44 | "fs1", 45 | "fa0", 46 | "fa1", 47 | "fa2", 48 | "fa3", 49 | "fa4", 50 | "fa5", 51 | "fa6", 52 | "fa7", 53 | "fs2", 54 | "fs3", 55 | "fs4", 56 | "fs5", 57 | "fs6", 58 | "fs7", 59 | "fs8", 60 | "fs9", 61 | "fs10", 62 | "fs11", 63 | "ft8", 64 | "ft9", 65 | "ft10", 66 | "ft11", 67 | "ustatus", 68 | "fflags", 69 | "frm", 70 | "fcsr", 71 | "uie", 72 | "utvec", 73 | ]; 74 | -------------------------------------------------------------------------------- /code-debug/src/mago.ts: -------------------------------------------------------------------------------- 1 | import { MI2DebugSession, RunCommand } from './mibase'; 2 | import { DebugSession, InitializedEvent, TerminatedEvent, StoppedEvent, OutputEvent, Thread, StackFrame, Scope, Source, Handles } from 'vscode-debugadapter'; 3 | import { DebugProtocol } from 'vscode-debugprotocol'; 4 | import { MI2_Mago } from "./backend/mi2/mi2mago"; 5 | import { SSHArguments, ValuesFormattingMode } from './backend/backend'; 6 | 7 | export interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArguments { 8 | cwd: string; 9 | target: string; 10 | magomipath: string; 11 | env: any; 12 | debugger_args: string[]; 13 | arguments: string; 14 | autorun: string[]; 15 | valuesFormatting: ValuesFormattingMode; 16 | printCalls: boolean; 17 | showDevDebugOutput: boolean; 18 | registerLimit: string; 19 | } 20 | 21 | export interface AttachRequestArguments extends DebugProtocol.AttachRequestArguments { 22 | cwd: string; 23 | target: string; 24 | magomipath: string; 25 | env: any; 26 | debugger_args: string[]; 27 | executable: string; 28 | autorun: string[]; 29 | stopAtConnect: boolean; 30 | valuesFormatting: ValuesFormattingMode; 31 | printCalls: boolean; 32 | showDevDebugOutput: boolean; 33 | registerLimit: string; 34 | } 35 | 36 | class MagoDebugSession extends MI2DebugSession { 37 | public constructor(debuggerLinesStartAt1: boolean, isServer: boolean = false) { 38 | super(debuggerLinesStartAt1, isServer); 39 | } 40 | 41 | protected override initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void { 42 | response.body.supportsHitConditionalBreakpoints = true; 43 | response.body.supportsConfigurationDoneRequest = true; 44 | response.body.supportsConditionalBreakpoints = true; 45 | response.body.supportsFunctionBreakpoints = true; 46 | response.body.supportsEvaluateForHovers = true; 47 | this.sendResponse(response); 48 | } 49 | 50 | getThreadID() { 51 | return 0; 52 | } 53 | 54 | protected override launchRequest(response: DebugProtocol.LaunchResponse, args: LaunchRequestArguments): void { 55 | const dbgCommand = args.magomipath || "mago-mi"; 56 | if (!this.checkCommand(dbgCommand)) { 57 | this.sendErrorResponse(response, 104, `Configured debugger ${dbgCommand} not found.`); 58 | return; 59 | } 60 | this.miDebugger = new MI2_Mago(dbgCommand, ["-q"], args.debugger_args, args.env); 61 | this.initDebugger(); 62 | this.quit = false; 63 | this.attached = false; 64 | this.initialRunCommand = RunCommand.RUN; 65 | this.isSSH = false; 66 | this.started = false; 67 | this.crashed = false; 68 | this.setValuesFormattingMode(args.valuesFormatting); 69 | this.miDebugger.printCalls = !!args.printCalls; 70 | this.miDebugger.debugOutput = !!args.showDevDebugOutput; 71 | this.miDebugger.registerLimit = args.registerLimit ?? ""; 72 | this.miDebugger.load(args.cwd, args.target, args.arguments, undefined, args.autorun || []).then(() => { 73 | this.sendResponse(response); 74 | }, err => { 75 | this.sendErrorResponse(response, 109, `Failed to load MI Debugger: ${err.toString()}`); 76 | }); 77 | } 78 | 79 | protected override attachRequest(response: DebugProtocol.AttachResponse, args: AttachRequestArguments): void { 80 | const dbgCommand = args.magomipath || "mago-mi"; 81 | if (!this.checkCommand(dbgCommand)) { 82 | this.sendErrorResponse(response, 104, `Configured debugger ${dbgCommand} not found.`); 83 | return; 84 | } 85 | this.miDebugger = new MI2_Mago(dbgCommand, ["-q"], args.debugger_args, args.env); 86 | this.initDebugger(); 87 | this.quit = false; 88 | this.attached = true; 89 | this.initialRunCommand = args.stopAtConnect ? RunCommand.NONE : RunCommand.CONTINUE; 90 | this.isSSH = false; 91 | this.setValuesFormattingMode(args.valuesFormatting); 92 | this.miDebugger.printCalls = !!args.printCalls; 93 | this.miDebugger.debugOutput = !!args.showDevDebugOutput; 94 | this.miDebugger.registerLimit = args.registerLimit ?? ""; 95 | this.miDebugger.attach(args.cwd, args.executable, args.target, args.autorun || []).then(() => { 96 | this.sendResponse(response); 97 | }, err => { 98 | this.sendErrorResponse(response, 110, `Failed to attach: ${err.toString()}`); 99 | }); 100 | } 101 | } 102 | 103 | DebugSession.run(MagoDebugSession); 104 | -------------------------------------------------------------------------------- /code-debug/src/path_kind.ts: -------------------------------------------------------------------------------- 1 | import * as Path from "path"; 2 | 3 | export abstract class PathKind { 4 | protected abstract readonly path: typeof Path.posix | typeof Path.win32; 5 | public abstract readonly caseSensitive: boolean; 6 | 7 | // The path.posix.normalize routine will not convert Win32 path separators 8 | // to POSIX separators, so we explictily convert any Win32 path separators 9 | // to POSIX style separators. The path.win32.normalize routine will accept 10 | // either Win32 or POSIX style separators and will normalize them to the 11 | // Win32 style. Thus, if we convert all path separators to POSIX style and 12 | // then normalize, this will work for both systems. 13 | public normalize(p: string): string { 14 | return this.path.normalize(p.replace(/\\/g, "/")); 15 | } 16 | 17 | public normalizeDir(p: string): string { 18 | p = this.normalize(p); 19 | if (!p.endsWith(this.path.sep)) p = this.path.join(p, this.path.sep); 20 | return p; 21 | } 22 | 23 | public join(...paths: string[]): string { 24 | return this.normalize(this.path.join(...paths)); 25 | } 26 | 27 | public isAbsolute(p: string): boolean { 28 | return this.path.isAbsolute(this.normalize(p)); 29 | } 30 | } 31 | 32 | export class PathWin32 extends PathKind { 33 | protected readonly path: typeof Path.posix | typeof Path.win32 = Path.win32; 34 | public readonly caseSensitive: boolean = false; 35 | private static instance: PathWin32; 36 | private constructor() { 37 | super(); 38 | } 39 | public static getInstance(): PathWin32 { 40 | if (!this.instance) this.instance = new PathWin32(); 41 | return this.instance; 42 | } 43 | } 44 | 45 | export class PathPosix extends PathKind { 46 | protected readonly path: typeof Path.posix | typeof Path.win32 = Path.posix; 47 | public readonly caseSensitive: boolean = true; 48 | private static instance: PathPosix; 49 | private constructor() { 50 | super(); 51 | } 52 | public static getInstance(): PathPosix { 53 | if (!this.instance) this.instance = new PathPosix(); 54 | return this.instance; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /code-debug/src/platform_specific.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/code-debug/src/platform_specific.ts -------------------------------------------------------------------------------- /code-debug/src/source_file_map.ts: -------------------------------------------------------------------------------- 1 | import { PathKind, PathWin32, PathPosix } from "./path_kind"; 2 | 3 | interface Mapping { 4 | remote: string; 5 | local: string; 6 | } 7 | 8 | export class SourceFileMap { 9 | private sortedMappings: { [key in keyof Mapping]: Mapping[] } = { 10 | remote: [], 11 | local: [], 12 | }; 13 | private nativePath: PathKind; 14 | private remoteCwd: string|undefined; 15 | 16 | constructor (map: { [index: string]: string }, remoteCwd?: string) { 17 | const mappings: Mapping[] = []; 18 | this.remoteCwd = remoteCwd; 19 | this.nativePath = this.getNativePath(); 20 | for (let [remotePrefix, localPrefix] of Object.entries(map)) { 21 | // Normalize local path, adding trailing separator if missing. 22 | localPrefix = this.nativePath.normalizeDir(localPrefix); 23 | 24 | // Try to detect remote path. 25 | const debuggerPath: PathKind = this.toPathKind(remotePrefix); 26 | // Normalize remote path, adding trailing separator if missing. 27 | remotePrefix = debuggerPath.normalizeDir(remotePrefix); 28 | 29 | mappings.push({ remote: remotePrefix, local: localPrefix }); 30 | } 31 | 32 | // Sort with longest paths first in case some paths are subsets, so that 33 | // we match the most appropriate (e.g., with path prefixes of '/home' 34 | // and '/home/foo', and a complete path of '/home/foo/bar.c', we should 35 | // match the '/home/foo' path prefix instead of '/home'. 36 | this.sortedMappings.local = [...mappings].sort( 37 | (a: Mapping, b: Mapping) => b.local.length - a.local.length 38 | ); 39 | this.sortedMappings.remote = [...mappings].sort( 40 | (a: Mapping, b: Mapping) => b.remote.length - a.remote.length 41 | ); 42 | } 43 | 44 | // The native path selection is isolated here to allow for easy unit testing 45 | // allowing non-native path types to be tested by overriding this method in 46 | // a subclass in the test harness. 47 | protected getNativePath(): PathKind { 48 | if (process.platform == "win32") return PathWin32.getInstance(); 49 | else return PathPosix.getInstance(); 50 | } 51 | 52 | private toPathKind(unknownPath: string): PathKind { 53 | const pathPosix: PathKind = PathPosix.getInstance(); 54 | const pathWin32: PathKind = PathWin32.getInstance(); 55 | 56 | if (pathPosix.isAbsolute(unknownPath) || 57 | (this.remoteCwd && pathPosix.isAbsolute(this.remoteCwd))) 58 | { 59 | return pathPosix; 60 | } else { 61 | return pathWin32; 62 | } 63 | } 64 | 65 | private pathMatch(key: keyof Mapping, caseSensitive: boolean, path: string): Mapping | undefined { 66 | for (const mapping of this.sortedMappings[key]) { 67 | let matched: boolean; 68 | 69 | if (caseSensitive) matched = path.startsWith(mapping[key]); 70 | else matched = path.toLowerCase().startsWith(mapping[key].toLowerCase()); 71 | 72 | if (matched) return mapping; 73 | } 74 | 75 | return undefined; 76 | } 77 | 78 | public toLocalPath(remotePath: string): string { 79 | // Try to detect remote path. 80 | const debuggerPath: PathKind = this.toPathKind(remotePath); 81 | const normalizedRemotePath: string = debuggerPath.normalize(remotePath); 82 | const mapping: Mapping | undefined = this.pathMatch( 83 | "remote", 84 | debuggerPath.caseSensitive, 85 | normalizedRemotePath 86 | ); 87 | 88 | if (mapping) { 89 | const pathSuffix = normalizedRemotePath.substring(mapping.remote.length); 90 | return this.nativePath.join(mapping.local, pathSuffix); 91 | } 92 | 93 | // No mapping found, so return unmapped path. 94 | return remotePath; 95 | } 96 | 97 | public toRemotePath(localPath: string): string { 98 | const normalizedLocalPath = this.nativePath.normalize(localPath); 99 | const mapping: Mapping | undefined = this.pathMatch( 100 | "local", 101 | this.nativePath.caseSensitive, 102 | normalizedLocalPath 103 | ); 104 | 105 | if (mapping) { 106 | const pathSuffix = normalizedLocalPath.substring(mapping.local.length); 107 | // Try to detect remote path. 108 | const debuggerPath = this.toPathKind(mapping.remote); 109 | return debuggerPath.join(mapping.remote, pathSuffix); 110 | } 111 | 112 | // No mapping found, so return unmapped path. 113 | return localPath; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /code-debug/src/test/unit/utils.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import { MIInfo, MINode } from '../../backend/mi_parse'; 3 | import { getAddrFromMINode, getPathFromMINode } from '../../utils'; 4 | 5 | suite("parser", () => { 6 | test("Test getAddrFromMINode", () => { 7 | const testMINode1: MINode = { 8 | "token": 43, 9 | "outOfBandRecord": [], 10 | "resultRecords": { 11 | "resultClass": "done", 12 | "results": [ 13 | [ 14 | "threads", [ 15 | [ 16 | ["id", "1"], 17 | ["target-id", "Thread 1.1"], 18 | ["details", "CPU#0 [running]"], 19 | [ 20 | "frame", [ 21 | ["level", "0"], 22 | ["addr", "0x0000000000010156"], 23 | ["func", "initproc::main"], 24 | ["args", []], 25 | ["file", "src/bin/initprocWW.rs"], 26 | ["fullname", "/home/czy/rCore-Tutorial-v3/user/src/bin/initproc.rs"], 27 | ["line", "13"], 28 | ["arch", "riscv:rv64"] 29 | ] 30 | ], 31 | [ 32 | "state", 33 | "stopped" 34 | ] 35 | ] 36 | ] 37 | ], 38 | [ 39 | "current-thread-id", 40 | "1" 41 | ] 42 | ] 43 | } 44 | } as MIInfo as MINode; 45 | assert.strictEqual(getAddrFromMINode(testMINode1), "0x0000000000010156"); 46 | }); 47 | test("Test getPathFromMINode", () => { 48 | const testMINode2: MINode = { 49 | "token": 23, 50 | "outOfBandRecord": [{ 51 | "isStream": false, 52 | "type": "exec", 53 | "asyncClass": "stopped", 54 | "output": [ 55 | ["reason", "end-stepping-range"], 56 | ["frame", [ 57 | ["addr", "0xffffffc0802cb77e"], 58 | ["func", "axtask::task::first_into_user"], 59 | ["args", [ 60 | [ 61 | ["name", "kernel_sp"], 62 | ["value", "18446743801062787952"] 63 | ], 64 | [ 65 | ["name", "frame_base"], 66 | ["value", "18446743801062787672"] 67 | ] 68 | ]], 69 | ["file", "modules/axtask/src/task.rs"], 70 | ["fullname", "/home/oslab/Starry/modules/axtask/src/task.rs"], 71 | ["line", "746"], 72 | ["arch", "riscv:rv64"] 73 | ]], 74 | ["thread-id", "1"], 75 | ["stopped-threads", "all"] 76 | ] 77 | }] 78 | } as MIInfo as MINode; 79 | assert.strictEqual(getPathFromMINode(testMINode2), "/home/oslab/Starry/modules/axtask/src/task.rs"); 80 | }); 81 | }); 82 | -------------------------------------------------------------------------------- /code-debug/src/utils.ts: -------------------------------------------------------------------------------- 1 | import { MIInfo, MINode } from "./backend/mi_parse"; 2 | import { FunctionString } from "./mibase"; 3 | 4 | export class ObjectAsFunction { 5 | functionArguments:string; 6 | functionBody:string; 7 | isAsync:boolean; 8 | constructor(argumentsString:string, functionBody:string, isAsync:boolean){ 9 | this.functionArguments = argumentsString; 10 | this.functionBody = functionBody; 11 | this.isAsync = isAsync; 12 | } 13 | 14 | } 15 | 16 | export function toFunctionString(o:ObjectAsFunction):FunctionString{ 17 | if(o.isAsync){ 18 | return `async (${o.functionArguments})=>{ ${o.functionBody} }`; 19 | } 20 | else { 21 | return `(${o.functionArguments})=>{${o.functionBody}}`; 22 | } 23 | } 24 | // /------------------------------------------------------------------------------------------_ 25 | // / This is bruteforce and ugly but the MINode is already a huge mess so I have to do this / 26 | // /-------------------------------------------------------------------------------------------/ 27 | // 😅 28 | export function getAddrFromMINode(info: MINode): string | undefined { 29 | const dfsCheckAddr = (obj: any): string | undefined => { 30 | for (const key in obj) { 31 | const value = obj[key]; 32 | if (Array.isArray(value)) { 33 | if (value.length === 2 && value[0] === "addr") { 34 | return value[1]; 35 | } 36 | } 37 | if (typeof value === "object") { 38 | const res = dfsCheckAddr(value); 39 | if (res != undefined) { 40 | return res; 41 | } 42 | } 43 | } 44 | return undefined; 45 | }; 46 | for (const output of info.outOfBandRecord) { 47 | const res = dfsCheckAddr(output); 48 | if (res != undefined) { 49 | return res; 50 | } 51 | } 52 | 53 | return dfsCheckAddr(info.resultRecords.results); 54 | } 55 | 56 | export function getPathFromMINode(info: MINode): string { 57 | const dfsCheckAddr = (obj: any): string | undefined => { 58 | for (const key in obj) { 59 | const value = obj[key]; 60 | if (Array.isArray(value)) { 61 | if (value.length === 2 && value[0] === "fullname") { 62 | return value[1]; 63 | } 64 | } 65 | if (typeof value === "object") { 66 | const res = dfsCheckAddr(value); 67 | if (res != undefined) { 68 | return res; 69 | } 70 | } 71 | } 72 | return undefined; 73 | }; 74 | for (const output of info.outOfBandRecord) { 75 | const res = dfsCheckAddr(output); 76 | if (res != undefined) { 77 | return res; 78 | } 79 | } 80 | return dfsCheckAddr(info.resultRecords.results); 81 | } 82 | 83 | 84 | 85 | export const prettyPrintJSON = (obj:any) => JSON.stringify( obj, (key, val) => (val instanceof Array) ? JSON.stringify(val) : val, 2).replace(/\\/g, '').replace(/\[/g, '[').replace(/\]/g, ']').replace(/\{/g, '{').replace(/\}/g, '}'); 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /code-debug/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "outDir": "out", 6 | "lib": [ 7 | "es6" 8 | ], 9 | "sourceMap": true, 10 | "rootDir": ".", 11 | "plugins": [ 12 | { 13 | "name": "tslint-language-service" 14 | } 15 | ], 16 | "noImplicitAny": true 17 | }, 18 | "exclude": [ 19 | "node_modules", 20 | ".vscode-test", 21 | "docs", 22 | "演示视频.mp4" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # FROM ubuntu:18.04 2 | 3 | FROM gitpod/openvscode-server:latest 4 | # 5 | 6 | # to get permissions to install packages and such 7 | USER root 8 | 9 | RUN sed -i 's/archive.ubuntu.com/mirrors.ustc.edu.cn/g' /etc/apt/sources.list 10 | 11 | RUN apt-get update && apt-get install -y \ 12 | vim zsh git g++ gdb python3 python3-pip python3-venv wget make unzip curl \ 13 | autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev \ 14 | gawk build-essential bison flex texinfo gperf libtool patchutils bc xz-utils \ 15 | zlib1g-dev libexpat-dev pkg-config libglib2.0-dev libpixman-1-dev tmux 16 | 17 | 18 | #install rust and qemu 19 | RUN set -x; \ 20 | RUSTUP='/home/workspace/rustup.sh' \ 21 | && cd $HOME \ 22 | #install rust 23 | && curl https://sh.rustup.rs -sSf > $RUSTUP && chmod +x $RUSTUP \ 24 | && $RUSTUP -y --default-toolchain nightly --profile minimal \ 25 | && echo done. \ 26 | #compile qemu 27 | && wget https://ftp.osuosl.org/pub/blfs/conglomeration/qemu/qemu-5.0.0.tar.xz \ 28 | && tar xvJf qemu-5.0.0.tar.xz \ 29 | && cd qemu-5.0.0 \ 30 | && ./configure --target-list=riscv64-softmmu,riscv64-linux-user \ 31 | && make -j$(nproc) install \ 32 | && cd $HOME && rm -rf qemu-5.0.0 qemu-5.0.0.tar.xz 33 | 34 | #for chinese network 35 | RUN set -x; \ 36 | APT_CONF='/etc/apt/sources.list'; \ 37 | CARGO_CONF='/home/workspace/.cargo/config'; \ 38 | BASHRC='/home/workspace/.bashrc' \ 39 | && echo 'export RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static' >> $BASHRC \ 40 | && echo 'export RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup' >> $BASHRC \ 41 | && touch $CARGO_CONF \ 42 | && echo '[source.crates-io]' > $CARGO_CONF \ 43 | && echo "replace-with = 'ustc'" >> $CARGO_CONF \ 44 | && echo '[source.ustc]' >> $CARGO_CONF \ 45 | && echo 'registry = "git://mirrors.ustc.edu.cn/crates.io-index"' >> $CARGO_CONF 46 | 47 | ENV PATH="$HOME/.cargo/bin:${PATH}" 48 | 49 | # some rust dependencies for rCore-Tutorial 50 | RUN rustup target add riscv64gc-unknown-none-elf 51 | RUN cargo install cargo-binutils --vers ~0.2 52 | RUN rustup component add rust-src 53 | RUN rustup component add llvm-tools-preview 54 | 55 | WORKDIR $HOME 56 | 57 | 58 | 59 | # this archive will be automatically unzipped. 60 | ADD ./riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz /home/workspace 61 | ADD ./gdb_startup_cmd.txt /home/workspace 62 | ADD ./Makefile /home/workspace 63 | 64 | 65 | 66 | 67 | # use mirror site due to annoying network 68 | # RUN git clone https://github.com.cnpmjs.org/rcore-os/rCore-Tutorial-v3.git 69 | RUN git clone https://hub.fastgit.xyz/chenzhiy2001/rCore-Tutorial-v3.git 70 | 71 | 72 | 73 | 74 | RUN chown -R openvscode-server:openvscode-server /home/workspace/ 75 | 76 | # to restore permissions for the web interface 77 | # USER openvscode-server 78 | 79 | # RUN python3 -m pip install --upgrade pip \ 80 | # && pip3 install gdbgui -i https://pypi.tuna.tsinghua.edu.cn/simple 81 | -------------------------------------------------------------------------------- /docker/Makefile: -------------------------------------------------------------------------------- 1 | TOOLCHAIN_NAME:=riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14 2 | GDB:=$(TOOLCHAIN_NAME)/bin/riscv64-unknown-elf-gdb 3 | GDB_STARTUP_CMD:=gdb_startup_cmd.txt 4 | PROJECT_NAME := rCore-Tutorial-v3 5 | TARGET := riscv64gc-unknown-none-elf 6 | MODE := release 7 | SYMBOL_BIN := $(PROJECT_NAME)/os/target/$(TARGET)/$(MODE)/os 8 | KERNEL_BIN := $(SYMBOL_BIN).bin 9 | FS_IMG := $(PROJECT_NAME)/user/target/$(TARGET)/$(MODE)/fs.img 10 | 11 | fast_github: 12 | @cd $(PROJECT_NAME) &&\ 13 | git config --global url."https://hub.fastgit.xyz/".insteadOf "https://github.com/" &&\ 14 | git config protocol.https.allow always 15 | 16 | 17 | unzip_toolchain: 18 | # no need. docker extracted tar.gz archive when building image 19 | # @tar -xvf $(TOOLCHAIN_NAME).tar.gz 20 | 21 | 22 | build: 23 | @cd $(PROJECT_NAME)/os && make build 24 | run: 25 | @qemu-system-riscv64 \ 26 | -machine virt \ 27 | -nographic \ 28 | -bios $(PROJECT_NAME)/bootloader/rustsbi-qemu.bin \ 29 | -device loader,file=$(KERNEL_BIN),addr=0x80200000 \ 30 | -drive file=$(FS_IMG),if=none,format=raw,id=x0 \ 31 | -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0\ 32 | -s -S 33 | 34 | ## need modify GDB_STARTUP_CMD 35 | run_gdbgui: 36 | @python3 -m gdbgui -r --gdb-cmd="$(GDB) -x $(GDB_STARTUP_CMD)" 37 | 38 | kill_qemu: 39 | @pkill qemu 40 | @pkill qemu-system-riscv64 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | # CoreDebugger-Docker 2 | 3 | ## 项目描述 4 | 5 | 本项目将实现一套适合操作系统开发的远程调试工具,主要由两部分组成: 6 | - docker容器提供在线vscode、rust工具链以及`qemu-system-riscv64`等调试[rCore-Tutorial-v3](https://rcore-os.github.io/rCore-Tutorial-Book-v3/index.html)所需要的工具(已基本完成) 7 | - 安装于在线vscode上的调试插件(基于Native Debug插件修改)。如下图所示,qemu在运行os时开启gdbserver,等待远程连接;vscode通过调试插件启动gdb,令其通过tcp协议连接gdbserver。 8 | ![](./overview.drawio.svg) 9 | 10 | 11 | 12 | 13 | ## 预期目标 14 | 15 | - [ ] 展现内核数据结构 16 | - [ ] 将gdb拿到的信息转换成符号 17 | - [ ] 支持函数调用的参数 18 | - [ ] 系统调用跟踪 19 | - [ ] 中断检测 20 | - [ ] 进程切换跟踪 21 | - [ ] 查看堆栈 22 | - [ ] rust优化 23 | - [ ] 宏 24 | - [ ] 高级功能 25 | - [ ] 文件存储 26 | - [ ] 花哨的图形界面 27 | - [ ] 上传镜像到docker hub 28 | - [ ] 支持uCore等其他项目 29 | - [ ] 符号表问题 30 | - [ ] 支持实体开发板 31 | - [ ] 文件存储功能 32 | ## 如何使用 33 | 34 | ### 构建docker容器 35 | 36 | 在[sifive官网](https://www.sifive.com/software)下载risc-v工具链(往下拉找到GNU Embedded Toolchain — v2020.12.8, 下载ubuntu版本), 37 | 或者试试直接访问 38 | [这里](https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-8.3.0-2020.04.1-x86_64-linux-ubuntu14.tar.gz)。下载后将该文件复制到本项目的目录下。 39 | 40 | 构建容器: 41 | ```shell 42 | docker build -t gdbgui-test . 43 | ``` 44 | ### 启动镜像 45 | ```dockerfile 46 | docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -it --rm -v $PWD:/sharedFolder --name gdbgui-test-1 -p 3000:3000 -p 5000:5000 gdbgui-test 47 | ``` 48 | 启动后,终端会提示在线vscode的网页地址,一般是`localhost:3000`。 49 | 50 | ### 编译、运行、调试 51 | 1. vscode打开您的项目文件夹 52 | 1. (在vscode中)`cd ..` 53 | 1. 安装Native Debug和rust-analyzer(可选)插件 54 | 1. 创建`launch.json`: 55 | ```json 56 | "configurations": [ 57 | { 58 | "type": "gdb", 59 | "request": "attach", 60 | "name": "Attach to qemu", 61 | "executable": "/home/workspace/rCore-Tutorial-v3/os/target/riscv64gc-unknown-none-elf/release/os", 62 | "target": ":1234", 63 | "remote": true, 64 | "cwd": "${workspaceRoot}", 65 | "valuesFormatting": "parseText", 66 | "gdbpath": "/home/workspace/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gdb" 67 | }, 68 | ] 69 | ``` 70 | 71 | 1. 将`/home/workspace/Makefile`中的`PROJECT_NAME`变量和`launch.json`中的`rCore-Tutorial-v3`修改为欲调试项目的文件夹名。 72 | 73 | 1. (可选)使用[github镜像站](https://doc.fastgit.org/zh-cn/guide.html): 74 | ```makefile 75 | make fast_github 76 | ``` 77 | 1. 编译、运行: 78 | ```makefile 79 | make build 80 | make run 81 | ``` 82 | 1. 点击▶按钮开始调试 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /docs/assets/images/2024-11-29202614.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/docs/assets/images/2024-11-29202614.png -------------------------------------------------------------------------------- /docs/assets/images/2024-12-06155429.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/docs/assets/images/2024-12-06155429.png -------------------------------------------------------------------------------- /docs/assets/images/image-20241206201635589.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/docs/assets/images/image-20241206201635589.png -------------------------------------------------------------------------------- /docs/readme.md: -------------------------------------------------------------------------------- 1 | # 关于 2 | 3 | 本文档用于记录调试工具[code-debug](https://github.com/chenzhiy2001/code-debug)的完成过程 4 | 5 | 本文档主要包括工具开发期间团队每一阶段的研发日志。 6 | + 工作记录 7 | 顺序记录我们完成的具体工作 8 | + 会议记录 9 | 倒叙记录每次开会的成员及会议内容 10 | # 导航 11 | 12 | - Record_1 13 | - [20240228](./docs/周报/record_1/20240228-具体工作.md) 14 | - [20240327](./docs/周报/record_1/20240327-具体工作.md) 15 | - [20240417](./docs/周报/record_1/20240417-具体工作.md) 16 | - [20240431](./docs/周报/record_1/20240431-具体工作.md) 17 | - [20240505](./docs/周报/record_1/20240505-具体工作.md) 18 | - [20240515](./docs/周报/record_1/20240515-具体工作.md) 19 | - [20240525](./docs/周报/record_1/20240525-具体工作.md) 20 | - [20240601](./docs/周报/record_1/20240601-具体工作.md) 21 | - [20240610](./docs/周报/record_1/20240610-具体工作.md) 22 | - [20240615](./docs/周报/record_1/20240615-具体工作.md) 23 | - [20240706](./docs/周报/record_1/20240706-具体工作.md) 24 | - [20240715](./docs/周报/record_1/20240715-具体工作.md) 25 | - [20240725](./docs/周报/record_1/20240725-具体工作.md) 26 | - [20240729](./docs/周报/record_1/20240729-具体工作.md) 27 | - [20240809](./docs/周报/record_1/20240809-具体工作.md) 28 | - [20240815](./docs/周报/record_1/20240815-具体工作.md) 29 | - Record_2 30 | - [20241206](./docs/周报/record_2/20241206-具体工作.md) 31 | - 会议记录 32 | - [会议记录_1](./docs/会议记录/会议记录_1.md) 33 | 34 | -------------------------------------------------------------------------------- /docs/周报/record_1/20240228-具体工作.md: -------------------------------------------------------------------------------- 1 | ### 20240228 2 | 1. 学习rust语言 3 | 2. 完成rcore实验 4 | 学习记录详见 5 | [杨雅棋的仓库](https://github.com/Kailning/code_r/tree/main/r-code) 6 | [张弈帆的仓库](https://github.com/fafa1412/OS-fafa/tree/main/r-core) 7 | -------------------------------------------------------------------------------- /docs/周报/record_1/20240327-具体工作.md: -------------------------------------------------------------------------------- 1 | ### 复现 2 | 3 | #### 遇到的问题及解决方案 4 | 5 | 6 | 1. 编译rcore-ebpf时修改user/ebpf/build.sh里面的路径 7 | 8 | ![a1cbe0e9ccb0000ee63ec8089e580c5](https://github.com/fafa1412/OS-fafa/assets/145512978/ce00f4f2-f1b0-4f3e-8526-7354c7faf346) 9 | 10 | 2. rust工具链配置出现问题时,可能需要手动修改一下文件里的版本,使用最新版 11 | 12 | ![328a0d2aef284b8cb7e0f5ac475ac08](https://github.com/fafa1412/OS-fafa/assets/145512978/733438b3-8d50-4ec1-95c2-67528eefdcfd) 13 | 14 | 3. 编译时找不到ruprobes 15 | 16 | 修改os/Cargo.toml中的ruprobes 17 | ruprobes = { git = "https://github.com/chenzhiy2001/ruprobes", features = ["rCore-Tutorial"] } 18 | 19 | 4. 编译时出现 unsafe {kprobes_breakpoint_handler(&mut *(_trap_cx as *const TrapContext as *mut TrapContext));} // ugly :(语句报错 20 | 21 | 尝试以下修改 22 | ``` 23 | unsafe {kprobes_breakpoint_handler(_trap_cx);} 24 | ``` 25 | 26 | 5. 修改launch.json文件如下: 27 | ``` 28 | //launch.json 29 | { 30 | "version": "0.2.0", 31 | "configurations": [ 32 | { 33 | "type": "gdb", 34 | "request": "attach", 35 | "name": "Attach to Qemu", 36 | "executable": "${userHome}/rcore-ebpf/os/target/riscv64gc-unknown-none-elf/release/os", 37 | "target": ":1234",//不能和Qemu开放的tcp端口重叠 38 | "remote": true, 39 | "cwd": "${workspaceRoot}", 40 | "valuesFormatting": "parseText", 41 | "gdbpath": "${workspaceRoot}/riscv64-unknown-elf-gdb-rust.sh", 42 | "showDevDebugOutput":true, 43 | "internalConsoleOptions": "openOnSessionStart", 44 | "printCalls": true, 45 | "stopAtConnect": true, 46 | "qemuPath": "qemu-system-riscv64", 47 | "qemuArgs": [ 48 | "-M", 49 | "128m", 50 | "-machine", 51 | "virt", 52 | "-bios", 53 | "${userHome}/rcore-ebpf/bootloader/rustsbi-qemu.bin", 54 | "-display", 55 | "none", 56 | "-device", 57 | "loader,file=${userHome}/rcore-ebpf/os/target/riscv64gc-unknown-none-elf/release/os.bin,addr=0x80200000", 58 | "-drive", 59 | "file=${userHome}/rcore-ebpf/user/target/riscv64gc-unknown-none-elf/release/fs.img,if=none,format=raw,id=x0", 60 | "-device", 61 | "virtio-blk-device,drive=x0", 62 | "-device", 63 | "virtio-gpu-device", 64 | "-device", 65 | "virtio-keyboard-device", 66 | "-device", 67 | "virtio-mouse-device", 68 | "-serial", 69 | "stdio", 70 | "-serial", 71 | "pty", 72 | "-s", 73 | "-S" 74 | ], 75 | 76 | "userSpaceDebuggeeFolder": "${userHome}/rcore-ebpf/user/target/riscv64gc-unknown-none-elf/release", 77 | "KERNEL_IN_BREAKPOINTS_LINE":65, // src/trap/mod.rs中内核入口行号。可能要修改 78 | "KERNEL_OUT_BREAKPOINTS_LINE":124, // src/trap/mod.rs中内核出口行号。可能要修改 79 | "GO_TO_KERNEL_LINE":30, // src/trap/mod.rs中,用于从用户态返回内核的断点行号。在rcore-ebpf中,这是set_user_trap_entry函数中的stvec::write(TRAMPOLINE as usize, TrapMode::Direct);语句。 80 | "KERNEL_IN_BREAKPOINTS_FILENAME":"${userHome}/rcore-ebpf/os/src/trap/mod.rs", 81 | "KERNEL_OUT_BREAKPOINTS_FILENAME":"${userHome}/rcore-ebpf/os/src/trap/mod.rs", 82 | "GO_TO_KERNEL_FILENAME":"", 83 | "kernel_memory_ranges":[["0xefffffffffffffff","0xffffffffffffffff"]], 84 | "user_memory_ranges":[["0x0000000000000000","0xe000000000000000"]] 85 | }, 86 | ] 87 | } 88 | ``` 89 | 6. 更新手动安装流程,编写自动安装流程 90 | 详见仓库首页readme 91 | -------------------------------------------------------------------------------- /docs/周报/record_1/20240417-具体工作.md: -------------------------------------------------------------------------------- 1 | ### 功能改进 2 | 3 | 1. 增加通过SSH进行OS调试的功能 4 | 2. 提升易用性,改进界面 5 | - 提升 Debug Console 输出内容的可读性 6 | - 测试、完善自动安装脚本 7 | - 提供帮助文档和帮助视频 8 | 3. 适配性提升 9 | - 增加配置文件的可配置项,提升可适配范围 10 | - 适配ArceOs 11 | 4. 改善开发体验 12 | - 清除硬编码代码,转换为可配置参数 13 | - 文档中详细解释核心代码 14 | - 添加单元测试 15 | -------------------------------------------------------------------------------- /docs/周报/record_1/20240431-具体工作.md: -------------------------------------------------------------------------------- 1 | ### 代码重构 2 | - 添加钩子断点 3 | - 修改launch.json 文件,用户可以里提交自定义代码 4 | - launch.json 支持${workspacefolder}插值(之前有一些参数是不能用这个插值的),大大提升了配置文件的便携性 5 | 如下所示: 6 | ``` 7 | // A launch configuration that compiles the extension and then opens it inside a new window 8 | { 9 | "version": "0.1.0", 10 | "configurations": [ 11 | { 12 | "name": "Launch Extension", 13 | "type": "extensionHost", 14 | "request": "launch", 15 | "runtimeExecutable": "${execPath}", 16 | "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], 17 | "stopOnEntry": false, 18 | "sourceMaps": true, 19 | "outFiles": [ 20 | "${workspaceRoot}/out/**/*.js" 21 | ], 22 | "preLaunchTask": "compile" 23 | }, 24 | { 25 | "name": "code-debug server", 26 | "type": "node", 27 | "request": "launch", 28 | "runtimeArgs": [ "--nolazy" ], 29 | "program": "${workspaceRoot}/src/gdb.ts", 30 | "stopOnEntry": false, 31 | "args": [ "--server=4711" ], 32 | "sourceMaps": true, 33 | "outFiles": [ 34 | "${workspaceRoot}/out/**/*.js" 35 | ], 36 | "cwd": "${workspaceRoot}", 37 | "preLaunchTask": "compile" 38 | }, 39 | { 40 | "name": "Launch Tests", 41 | "type": "extensionHost", 42 | "request": "launch", 43 | "runtimeExecutable": "${execPath}", 44 | "args": [ 45 | "--extensionDevelopmentPath=${workspaceRoot}", 46 | "--extensionTestsPath=${workspaceRoot}/out/src/test/suite/index" 47 | ], 48 | "stopOnEntry": false, 49 | "sourceMaps": true, 50 | "outFiles": [ 51 | "${workspaceRoot}/out/**/*.js" 52 | ], 53 | "preLaunchTask": "compile" 54 | } 55 | ], 56 | "compounds": [ 57 | { 58 | "name": "Extension Debugging (Extension + Debug Server)", 59 | "configurations": ["Launch Extension", "code-debug server"] 60 | }, 61 | ] 62 | } 63 | ``` 64 | 65 | - 添加足够多的代码抽象 66 | - 边界断点除了通过配置文件添加,也可以通过右键菜单添加(甚至可以取消) 67 | - 删除冗余代码,类似"地址空间"的变量名全部改成“断点组” 68 | - 解决了由调试器自动设置的断点不会在 VSCode 里面显示出来的问题 69 | - 添加了 showInformationMessage 函数,代替 mibase.ts 中无法使用的 console.log 70 | - 修改插件本身的编译配置文件 tsconfig.json,使得编译本插件的时候忽略文档文件夹和根文件夹下 60m 的“演示视频.mp4”,从而极大减小编译出的插件二进制包的大小 71 | -------------------------------------------------------------------------------- /docs/周报/record_1/20240505-具体工作.md: -------------------------------------------------------------------------------- 1 | ## xv6-riscv 2 | xv6-riscv 是 MIT 操作系统课程的教学操作系统 xv6 的 RISC-V 移植版本。 3 | RISC-V 是一种开源的指令集架构 (ISA), 4 | 被设计为一个可以广泛使用的通用 ISA。 5 | ### 1. **系统概述** 6 | 7 | xv6-riscv 是一个小型的 Unix 第六版操作系统实现,包含了基本的操作系统功能,如进程管理、内存管理、文件系统、设备驱动和系统调用。 8 | 9 | ### 2. **内核架构** 10 | 11 | #### 内核结构 12 | 13 | xv6-riscv 采用单内核结构,所有的操作系统服务都在内核模式下运行。内核代码包括内存管理、进程管理、文件系统、驱动程序和系统调用接口等部分。 14 | 15 | #### 启动过程 16 | 17 | 1. **启动加载器**:系统启动时,启动加载器将 xv6-riscv 内核从磁盘加载到内存,并将控制权转交给内核。 18 | 2. **内核初始化**:内核启动后,进行硬件初始化,设置中断向量表,初始化内存管理和进程管理子系统。 19 | 3. **用户进程启动**:初始化完毕后,内核启动第一个用户进程(通常是 `init` 进程)。 20 | 21 | ### 3. **进程管理** 22 | 23 | #### 进程结构 24 | 25 | - **进程控制块 (PCB)**:每个进程都有一个 PCB,其中包含进程的状态信息,如寄存器内容、内存映射、文件描述符等。 26 | - **进程状态**:进程可以处于运行、就绪、阻塞或终止状态。 27 | 28 | #### 进程调度 29 | 30 | - **调度算法**:xv6-riscv 使用简单的轮转调度算法。调度器在多个就绪进程之间循环切换,确保每个进程都能得到运行机会。 31 | 32 | #### 上下文切换 33 | 34 | - **保存和恢复上下文**:上下文切换时,内核保存当前运行进程的寄存器状态,并加载下一个进程的寄存器状态。 35 | 36 | ### 4. **内存管理** 37 | 38 | #### 地址空间 39 | 40 | - **虚拟内存**:每个进程都有独立的虚拟地址空间。xv6-riscv 使用页表实现虚拟内存,提供进程隔离和内存保护。 41 | - **分页机制**:支持基本的分页机制,每个页的大小为 4KB。 42 | 43 | #### 内存分配 44 | 45 | - **内核分配器**:内核使用简单的分配器进行内存管理,如 `kalloc` 和 `kfree`。 46 | - **用户空间分配器**:用户进程使用类似于 Unix 的 `sbrk` 系统调用来分配和释放内存。 47 | 48 | ### 5. **文件系统** 49 | 50 | #### 文件结构 51 | 52 | - **inode**:每个文件和目录都有一个 inode,包含文件的元数据和数据块指针。 53 | - **目录结构**:目录也是特殊的文件,包含目录项,目录项指向文件的 inode。 54 | 55 | #### 文件操作 56 | 57 | - **文件描述符**:进程通过文件描述符进行文件操作,如打开、读写、关闭文件。 58 | - **系统调用**:提供一组系统调用,如 `open`、`read`、`write`、`close` 等,实现文件操作。 59 | 60 | ### 6. **设备驱动** 61 | 62 | #### I/O 设备 63 | 64 | - **终端设备**:支持基本的终端输入输出。 65 | - **磁盘设备**:支持磁盘读写操作,提供块设备接口。 66 | 67 | #### 中断处理 68 | 69 | - **中断向量表**:内核初始化时设置中断向量表,将硬件中断映射到相应的中断处理程序。 70 | - **中断处理程序**:处理硬件中断,如时钟中断、设备中断等。 71 | 72 | ### 7. **系统调用接口** 73 | 74 | xv6-riscv 提供了一组基本的系统调用,供用户进程使用。这些系统调用包括进程管理、文件操作和内存管理等。 75 | 76 | - **进程管理**:`fork`、`exec`、`exit`、`wait` 等。 77 | - **文件操作**:`open`、`read`、`write`、`close`、`link`、`unlink` 等。 78 | - **内存管理**:`sbrk` 系统调用,用于动态内存分配。 79 | 80 | ### 8. **代码结构** 81 | 82 | xv6-riscv 的源代码非常简洁,分为多个模块,每个模块对应操作系统的一个子系统: 83 | 84 | - **kernel/**:内核核心代码,包括进程管理、内存管理、中断处理等。 85 | - **fs/**:文件系统代码。 86 | - **user/**:用户空间程序,包括基本的 Unix 工具和测试程序。 87 | - **include/**:头文件目录,定义了内核和用户程序使用的各种数据结构和常量。 88 | - **boot/**:启动加载器代码。 89 | 90 | ### 总结 91 | 92 | xv6-riscv 是一个移植到 RISC-V 架构上的 Unix 第六版操作系统实现,设计简洁,功能完备。它包括进程管理、内存管理、文件系统、设备驱动和系统调用接口等基本操作系统功能。 93 | -------------------------------------------------------------------------------- /docs/周报/record_1/20240515-具体工作.md: -------------------------------------------------------------------------------- 1 | ### 配置xv6运行环境 2 | 根据[xv6-riscv](https://github.com/mit-pdos/xv6-riscv)文档配置xv6运行环境 3 | 用**make**指令进行编译,**make qemu**编译并启动 4 | ![image](https://github.com/user-attachments/assets/44bd46c7-07eb-481d-ba86-3f4d3ce02904) 5 | ![屏幕截图 2024-07-30 122312](https://github.com/user-attachments/assets/d2ecba75-4ca4-4eca-9e7b-ea2a5d7d1000) 6 | 7 | ### 找到xv6启动参数,尝试编写配置文件 8 | 根据自己的理解,写出xv6推荐的qemu启动参数 9 | ``` 10 | "qemuArgs": [ 11 | "-M", 12 | "128m", 13 | "-machine", 14 | "virt", 15 | "-bios", 16 | "${workspaceFolder}/bootloader/rustsbi-qemu.bin", 17 | "-display", 18 | "none", 19 | "-drive", 20 | "file=${workspaceFolder}/fs.img,if=none,format=raw,id=x0", 21 | "-device", 22 | "virtio-blk-device,drive=x0", 23 | "-device", 24 | "virtio-gpu-device", 25 | "-device", 26 | "virtio-keyboard-device", 27 | "-device", 28 | "virtio-mouse-device", 29 | "-device", 30 | "virtio-net-device,netdev=net0", 31 | "-netdev", 32 | "user,id=net0,hostfwd=udp::6200-:2000,hostfwd=tcp::6201-:80", 33 | "-serial", 34 | "stdio", 35 | "-serial", 36 | "pty", 37 | "-s", 38 | "-S" 39 | ], 40 | ```` 41 | -------------------------------------------------------------------------------- /docs/周报/record_1/20240525-具体工作.md: -------------------------------------------------------------------------------- 1 | ### 尝试移植 2 | 找内核和用户的边界和行号,钩子断点的文件和行号 3 | #### 可能的文件: 4 | + sysproc.c 5 | + trap.c 6 | + syscall.c 7 | + sysfile.c 8 | #### 初步尝试: 9 | ``` 10 | launch.json 11 | { 12 | "version": "0.2.0", 13 | "configurations": [ 14 | 15 | { 16 | "type": "gdb", 17 | "request": "attach", 18 | "name": "Attach to Qemu", 19 | "autorun": ["add-symbol-file ${workspaceFolder}/kernel/kernel"], 20 | "target": ":1234", 21 | "remote": true, 22 | "cwd": "/home/kaining/xv6-riscv", 23 | "valuesFormatting": "parseText", 24 | "gdbpath": "${workspaceFolder}/riscv64-unknown-elf-gdb-rust.sh", 25 | "showDevDebugOutput":true, 26 | "internalConsoleOptions": "openOnSessionStart", 27 | "printCalls": true, 28 | "stopAtConnect": true, 29 | "qemuPath": "${workspaceFolder}/qemu-system-riscv64-with-logs.sh", 30 | "qemuArgs": [ 31 | "-machine", 32 | "virt", 33 | "-bios", 34 | "none", 35 | "-kernel", 36 | "kernel/kernel", 37 | "-m", 38 | "128M", 39 | "-smp", 40 | "2", 41 | "-nographic", 42 | "-global", 43 | "virtio-mmio.force-legacy=false", 44 | "-drive", 45 | "file=fs.img,if=none,format=raw,id=x0", 46 | "-device", 47 | "virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0", 48 | 49 | "-device", 50 | "virtio-gpu-device", 51 | "-device", 52 | "virtio-keyboard-device", 53 | "-device", 54 | "virtio-mouse-device", 55 | 56 | "-serial", 57 | "pty", 58 | "-s", 59 | "-S" 60 | ], 61 | "program_counter_id": 32, 62 | "first_breakpoint_group": "kernel", 63 | "second_breakpoint_group":"${workspaceFolder}/user/init.c", 64 | "kernel_memory_ranges":[["0x80000000","0xffffffffffffffff"]], 65 | "user_memory_ranges":[["0x0000000000000000","0x80000000"]], 66 | "border_breakpoints":[ 67 | { 68 | "filepath": "${workspaceFolder}/kernel/syscall.c", 69 | "line": 141 70 | }, 71 | { 72 | "filepath": "${workspaceFolder}/kernel/trap.c", 73 | "line": 105 74 | } 75 | ], 76 | "hook_breakpoints":[ 77 | { 78 | "breakpoint": { 79 | "file": "${workspaceFolder}/kernel/sysfile.c", 80 | "line": 441 81 | }, 82 | "behavior": { 83 | "isAsync": true, 84 | "functionArguments": "", 85 | "functionBody": "let p=await this.getStringVariable('path'); return '${workspaceFolder}/user/'+p+'.c'" 86 | } 87 | } 88 | ], 89 | "filePathToBreakpointGroupNames":{ 90 | "isAsync": false, 91 | "functionArguments": "filePathStr", 92 | "functionBody": " if (filePathStr.includes('kernel')) { return ['kernel']; } else if (filePathStr.includes('user')) { return [filePathStr]; } else return ['kernel'];" 93 | }, 94 | "breakpointGroupNameToDebugFilePath":{ 95 | "isAsync": false, 96 | "functionArguments": "groupName", 97 | "functionBody": "if (groupName === 'kernel') {return '${workspaceFolder}/kernel';} else{ let pathSplited = groupName.split('/'); let filename = pathSplited[pathSplited.length - 1].split('.'); let filenameWithoutExtension = filename.slice(0, -1).join('.'); return '${workspaceFolder}/user/' + filenameWithoutExtension;}" 98 | 99 | } 100 | }, 101 | ], 102 | } 103 | 104 | ``` 105 | ### 存在的问题 106 | + vscode的终端一直没有输出 107 | + 只能够进行内核到用户态的转换 108 | -------------------------------------------------------------------------------- /docs/周报/record_1/20240601-具体工作.md: -------------------------------------------------------------------------------- 1 | ### 修改qemu启动参数 2 | launch文件写完之后,我们发现vscode终端一直没有输出,排查之后发现是因为之前qemu的路径沿用ebpf的路径,经过修改后可以正常输入了。 3 | ``` 4 | launch.json 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | 9 | { 10 | "type": "gdb", 11 | "request": "attach", 12 | "name": "Attach to Qemu", 13 | "autorun": ["add-symbol-file ${workspaceFolder}/kernel/kernel"], 14 | "target": ":1234", 15 | "remote": true, 16 | "cwd": "/home/kaining/xv6-riscv", 17 | "valuesFormatting": "parseText", 18 | "gdbpath": "${workspaceFolder}/riscv64-unknown-elf-gdb-rust.sh", 19 | "showDevDebugOutput":true, 20 | "internalConsoleOptions": "openOnSessionStart", 21 | "printCalls": true, 22 | "stopAtConnect": true, 23 | "qemuPath": "$qemu-system-riscv64", 24 | "qemuArgs": [ 25 | "-machine", 26 | "virt", 27 | "-bios", 28 | "none", 29 | "-kernel", 30 | "kernel/kernel", 31 | "-m", 32 | "128M", 33 | "-smp", 34 | "2", 35 | "-nographic", 36 | "-global", 37 | "virtio-mmio.force-legacy=false", 38 | "-drive", 39 | "file=fs.img,if=none,format=raw,id=x0", 40 | "-device", 41 | "virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0", 42 | "-s", 43 | "-S" 44 | ], 45 | "program_counter_id": 32, 46 | "first_breakpoint_group": "kernel", 47 | "second_breakpoint_group":"${workspaceFolder}/user/init.c", 48 | "kernel_memory_ranges":[["0x80000000","0xffffffffffffffff"]], 49 | "user_memory_ranges":[["0x0000000000000000","0x80000000"]], 50 | "border_breakpoints":[ 51 | { 52 | "filepath": "${workspaceFolder}/kernel/syscall.c", 53 | "line": 141 54 | }, 55 | { 56 | "filepath": "${workspaceFolder}/kernel/trap.c", 57 | "line": 105 58 | } 59 | ], 60 | "hook_breakpoints":[ 61 | { 62 | "breakpoint": { 63 | "file": "${workspaceFolder}/kernel/sysfile.c", 64 | "line": 441 65 | }, 66 | "behavior": { 67 | "isAsync": true, 68 | "functionArguments": "", 69 | "functionBody": "let p=await this.getStringVariable('path'); return '${workspaceFolder}/user/'+p+'.c'" 70 | } 71 | } 72 | ], 73 | "filePathToBreakpointGroupNames":{ 74 | "isAsync": false, 75 | "functionArguments": "filePathStr", 76 | "functionBody": " if (filePathStr.includes('kernel')) { return ['kernel']; } else if (filePathStr.includes('user')) { return [filePathStr]; } else return ['kernel'];" 77 | }, 78 | "breakpointGroupNameToDebugFilePath":{ 79 | "isAsync": false, 80 | "functionArguments": "groupName", 81 | "functionBody": "if (groupName === 'kernel') {return '${workspaceFolder}/kernel';} else{ let pathSplited = groupName.split('/'); let filename = pathSplited[pathSplited.length - 1].split('.'); let filenameWithoutExtension = filename.slice(0, -1).join('.'); return '${workspaceFolder}/user/' + filenameWithoutExtension;}" 82 | 83 | } 84 | }, 85 | ], 86 | } 87 | ``` 88 | ### 存在的问题 89 | 但是调试器只能进行内核到用户的切换,不能进行用户态到内核态的转换,还需要继续排查原因 90 | -------------------------------------------------------------------------------- /docs/周报/record_1/20240610-具体工作.md: -------------------------------------------------------------------------------- 1 | 虚拟机意外打不开了,使用我们编写的安装与使用文档进行安装,遇到一些新的问题。 2 | ![微信图片_20240730160739](https://github.com/user-attachments/assets/3399c69f-c807-42a8-aead-a7b1514cb1b9) 3 | 这段代码怎么改都是错的,最后把channel改成channel = "nightly-2023-08-05"就可以了。 4 | 出错的这个info.message()是属于rust的核心库core,我们猜测应该是rust自己核心库和编译器有bug。 5 | ![微信图片_20240730161144](https://github.com/user-attachments/assets/6c07321f-946f-41a6-bfbe-460ec2587d8a) 6 | 出现这个情况需要到codedebug/codedebug目录下输入 7 | ``` 8 | nmp install 9 | ``` 10 | 注意如果npm版本过低需要先更新 11 | **需要准备把遇到的问题写到安装与使用里。** 12 | -------------------------------------------------------------------------------- /docs/周报/record_1/20240615-具体工作.md: -------------------------------------------------------------------------------- 1 | #### 修改package.json 2 | 原来的调试器仅rust语言可见,现在修改为所有文件可见 3 | ``` 4 | "menus": { 5 | "editor/title": [ 6 | { 7 | "when": "resourceLangId == true", 8 | "command": "code-debug.removeAllCliBreakpoints", 9 | "group": "navigation" 10 | }, 11 | { 12 | "when": "resourceLangId == true", 13 | "command": "code-debug.setBorderBreakpointsFromLaunchJSON", 14 | "group": "navigation" 15 | }, 16 | { 17 | "when": "resourceLangId == true", 18 | "command": "code-debug.setHookBreakpointsFromLaunchJSON", 19 | "group": "navigation" 20 | }, 21 | { 22 | "when": "resourceLangId == true", 23 | "command": "code-debug.disableCurrentSpaceBreakpoints", 24 | "group": "navigation" 25 | } 26 | ], 27 | ``` 28 | #### 修改获取路径函数 29 | ``` 30 | "breakpointGroupNameToDebugFilePath":{ 31 | "isAsync": false, 32 | "functionArguments": "groupName", 33 | "functionBody": "if (groupName === 'kernel') { return '${workspaceFolder}/kernel/kernel'; } else { let pathSplited = groupName.split('/'); let filename = pathSplited[pathSplited.length - 1].split('.'); let filenameWithoutExtension = filename[filename.length - 2]; return '${workspaceFolder}/user/' + '_' + filenameWithoutExtension; }" 34 | } 35 | ``` 36 | xv6的用户文件经过编译后为_+文件名,开始没有注意到_ ,后面才发现这个小细节 37 | -------------------------------------------------------------------------------- /docs/周报/record_1/20240706-具体工作.md: -------------------------------------------------------------------------------- 1 | 由于没有找到调试器只能进行内核到用户态转换,而不能进行用户态到内核态转换的原因,我们决定调试调试器进一步排查原因。 2 | ## 调试code-debug 3 | 相关文档 4 | Debugger Extension | Visual Studio Code Extension API 5 | ### 调试器的构成及调试 6 | code-debug插件分为两部分,扩展和调试适配器,这两部分是由两个进程来控制。所以如果调试的话应该是启动两个调试配置,一个是launch extension,另一个是server。 7 | + launch extension 8 | 调试extension的部分,更具体地说是extension.ts文件,用它调试就会启动一个新窗口(扩展开发宿主) 9 | + server 10 | 调试调试适配器的部分,即除了extension.ts文件的其他文件,这部分的调试需要进行一个配置(code-debug sever的调试配置),在code-debug中的launch.json已经配置好了, 11 | 里面有一个4711的端口号,启动这个配置以后,会监听这个端口号。 12 | 所以,在我们要调试的项目中,添加一个``` "debugServer": 4711,```的配置,使两者可以传递信息。 13 | 14 | ### 具体调试步骤: 15 | 在code-debug中找到调试的界面,选择launch extension,然后按F5,启动一个新窗口,在新窗口中选择要调试的项目打开,然后不要动。 16 | 回到code-debug的调试界面,点击调试和运行的下拉框,选择code-debug sever,点击绿色的开始调试按钮,就会发现多了一个调试配置,如下图。 17 | ![image](https://github.com/user-attachments/assets/5cfd22bc-75bc-44ce-a4d9-b4591ab73287) 18 | 19 | 20 | 接下来,回到新窗口,按F5,按照正常的调试流程进行操作,会触发在文件中设置的断点(推荐的断点位置mibase.ts中的handleBreakpoint()函数中)。 21 | 22 | + 关于断点设置: 尽量不要在extension.ts里面设置断点,会卡在那里,最后终止程序。 23 | + 关于console.log函数的输出: 对于上面两个启动配置,会有两个调试控制台,在不同文件中的输出会在不同的调试控制台中。 24 | -------------------------------------------------------------------------------- /docs/周报/record_1/20240715-具体工作.md: -------------------------------------------------------------------------------- 1 | #### 在使用调试手段后,我们发现不能从用户态转换到内核态的原因是用户的边界没有被正确设置。 2 | + kernel/syscall.c是负责处理已经进到内核之后的syscall处理流程。 3 | + 我们需要的是用户态的syscall接口,在usys.S里面。 4 | 因为usys.S是由usys.pl生成的汇编代码,之前被我们忽略掉了。 5 | #### 将用户态边界文件换成usys.S 6 | ``` 7 | "border_breakpoints":[ 8 | { 9 | "filepath": "${workspaceFolder}/user/usys.S", 10 | "line":6 11 | }, 12 | { 13 | "filepath": "${workspaceFolder}/kernel/trap.c", 14 | "line":129 15 | } 16 | ], 17 | ``` 18 | 其他地方也相应调整 19 | ``` 20 | "filePathToBreakpointGroupNames": { 21 | "isAsync": false, 22 | "functionArguments": "filePathStr", 23 | "functionBody": "if (filePathStr.includes('kernel')) { return ['kernel']; } else if (filePathStr === '${workspaceFolder}/user/usys.S') { return ['${workspaceFolder}/user/ln.c', '${workspaceFolder}/user/ls.c', '${workspaceFolder}/user/rm.c', '${workspaceFolder}/user/sh.c', '${workspaceFolder}/user/wc.c', '${workspaceFolder}/user/cat.c', '${workspaceFolder}/user/echo.c', '${workspaceFolder}/user/grep.c', '${workspaceFolder}/user/init.c', '${workspaceFolder}/user/kill.c', '${workspaceFolder}/user/ulib.c', '${workspaceFolder}/user/grind.c', '${workspaceFolder}/user/mkdir.c', '${workspaceFolder}/user/printf.c', '${workspaceFolder}/user/zombie.c', '${workspaceFolder}/user/umalloc.c', '${workspaceFolder}/user/forktest.c', '${workspaceFolder}/user/stressfs.c', '${workspaceFolder}/user/usertests.c']; } else if (filePathStr.includes('user') && filePathStr !== '${workspaceFolder}/user/usys.S') { return [filePathStr]; } else { return ['kernel']; }" 24 | }, 25 | ``` 26 | 27 | 换完之后发现此时可以进行内核和用户之间的切换了,但只能在第一个断点处。 28 | 经过调试后发现原因如下: 29 | + 因为usys.S文件中有多个ecall,也就是说用户态有多个边界断点(因为xv6在用户态没有一个专门的syscall()处理函数,而是每个syscall的调用单独处理)。 30 | + 我们的调试器一开始是基于ebpf写的,所以用户和内核的边界都只有一个,接下来需要将边界改成数组,添加新的边界断点时旧的会被替换掉 31 | 32 | #### 修改code-debug代码 33 | + 我们决定将原本的边界改成数组来解决上述问题。 34 | 在launch.json里面只指定边界断点,没有指定边界断点所属的断点组。边界断点所属的断点组是由调试器自己去判定的。所以当触发了多个断点组中的一个, 35 | 调试器就会判定这个边界断点属于某某断点组,然后进行断点组切换的流程。 36 | ``` 37 | export class Border { 38 | filepath:string; 39 | line:number; 40 | constructor(filepath:string, line:number){ 41 | this.filepath = filepath; 42 | this.line = line; 43 | } 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /docs/周报/record_1/20240725-具体工作.md: -------------------------------------------------------------------------------- 1 | #### 修改code-debug 2 | 接着上周未完成的工作相应修改相关函数,经过以下修改,现在调试器已经可以设置多个边界并且能正常切换。 3 | ``` 4 | class BreakpointGroup { 5 | name: string; 6 | setBreakpointsArguments: DebugProtocol.SetBreakpointsArguments[]; 7 | borders?:Border[]; // can be a border or undefined 8 | hooks:HookBreakpoints; //cannot be `undefined`. It should at least an empty array `[]`. 9 | constructor(name: string, setBreakpointsArguments: DebugProtocol.SetBreakpointsArguments[], hooks:HookBreakpoints, borders?:Border[] ) { 10 | console.log(name); 11 | this.name = name; 12 | this.setBreakpointsArguments = setBreakpointsArguments; 13 | this.hooks = hooks; 14 | this.borders = borders; 15 | } 16 | } 17 | public updateBorder(border: Border) { 18 | const result = eval(this.debugSession.filePathToBreakpointGroupNames)(border.filepath); 19 | const groupNamesOfBorder:string[] = result; 20 | for(const groupNameOfBorder of groupNamesOfBorder){ 21 | let groupExists = false; 22 | for(const group of this.groups){ 23 | if(group.name === groupNameOfBorder){ 24 | groupExists = true; 25 | group.borders.push(border); 26 | } 27 | } 28 | if(groupExists === false){ 29 | this.groups.push(new BreakpointGroup(groupNameOfBorder, [], new HookBreakpoints([]), [border])); 30 | } 31 | } 32 | } 33 | else if(action.type === DebuggerActions.check_if_kernel_to_user_border_yet){ 34 | this.showInformationMessage('doing action: check_if_kernel_to_user_border_yet'); 35 | let filepath:string = ""; 36 | let lineNumber:number = -1; 37 | const kernelToUserBorders = this.breakpointGroups.getCurrentBreakpointGroup().borders; // 获取所有边界断点 38 | //const kernelToUserBorderFile = this.breakpointGroups.getCurrentBreakpointGroup().border?.filepath; 39 | //const kernelToUserBorderLine = this.breakpointGroups.getCurrentBreakpointGroup().border?.line; 40 | //todo if you are trying to do multi-core debugging, you might need to modify the 3rd argument. 41 | this.miDebugger.getStack(0, 1, this.recentStopThreadID).then(v=>{ 42 | filepath = v[0].file; 43 | lineNumber = v[0].line; 44 | 45 | if (kernelToUserBorders) { 46 | for (const border of kernelToUserBorders) { 47 | if (filepath === border.filepath && lineNumber === border.line) { 48 | this.OSStateTransition(new OSEvent(OSEvents.AT_KERNEL_TO_USER_BORDER)); 49 | break; 50 | } 51 | } 52 | } 53 | }); 54 | 55 | } 56 | // obviously we are at current user breakpoint group when executing this action 57 | else if(action.type === DebuggerActions.check_if_user_to_kernel_border_yet){ 58 | this.showInformationMessage('doing action: check_if_user_to_kernel_border_yet'); 59 | let filepath:string = ""; 60 | let lineNumber:number = -1; 61 | const userToKernelBorders = this.breakpointGroups.getCurrentBreakpointGroup().borders; // 获取所有边界断点 62 | //const userToKernelBorderFile = this.breakpointGroups.getCurrentBreakpointGroup().border?.filepath; 63 | //const userToKernelBorderLine = this.breakpointGroups.getCurrentBreakpointGroup().border?.line; 64 | //todo if you are trying to do multi-core debugging, you might need to modify the 3rd argument. 65 | this.miDebugger.getStack(0, 1, this.recentStopThreadID).then(v=>{ 66 | filepath = v[0].file; 67 | lineNumber = v[0].line; 68 | 69 | // 检查当前的文件路径和行号是否与任何一个边界断点匹配 70 | if (userToKernelBorders) { 71 | for (const border of userToKernelBorders) { 72 | if (filepath === border.filepath && lineNumber === border.line) { 73 | this.OSStateTransition(new OSEvent(OSEvents.AT_USER_TO_KERNEL_BORDER)); 74 | break; 75 | } 76 | } 77 | } 78 | }); 79 | 80 | } 81 | ``` 82 | #### 存在的问题 83 | 现在只剩一个问题,就是钩子断点触发后返回的值是错误的,这也是为什么调试器会自己中断的原因。 84 | -------------------------------------------------------------------------------- /docs/周报/record_1/20240809-具体工作.md: -------------------------------------------------------------------------------- 1 | ## 硬件部分的准备工作 2 | 我们选择的单板计算机是昉·星光2 3 | 昉·星光 2 搭载四核64位RV64GC ISA的芯片平台(SoC),工作频率最高可达1.5 GHz,集成IMG BXE-4-32,支持OpenCL 3.0,OpenGL ES 3.2和Vulkan 1.2。昉·星光 2提供2/4/8 GB LPDDR4 RAM选项,外设I/O接口丰富,包括M.2接口、eMMC插座、USB 3.0接口、40-pin GPIO header、千兆以太网接口、TF卡插槽等。昉·星光 2不仅配有板载音频处理和视频处理能力,还具有多媒体外设接口MIPI-CSI和MIPI-DSI。开源的昉·星光 2具有强大的软件适配性,官方适配Debian操作系统,同时通过社区合作适配各种Linux发行版,包括Ubuntu、OpenSUSE、OpenKylin、OpenEuler、Deepin等,及在这些操作系统上运行的各类软件。 4 | ### 昉·星光2 5 | ![image](https://github.com/user-attachments/assets/c49e6458-8c6b-47bc-8cf9-0897629a04f8) 6 | ![image](https://github.com/user-attachments/assets/3c09da05-7e73-473c-8a3b-fb9f8652c667) 7 | ![image](https://github.com/user-attachments/assets/343ed156-a313-48ab-9f40-22fe087946d2) 8 | ![image](https://github.com/user-attachments/assets/ecea122d-2256-44fa-b8c6-c1f423ed829a) 9 | ### 连接 10 | 经过研究,我们决定用**J-Link** ARM仿真转换器进行连接,原因如下: 11 | + 高效的调试性能 12 | J-Link 提供了非常快的调试速度,支持高速下载代码和实时调试。它可以通过 JTAG 接口与目标微控制器连接,使得调试过程中的响应时间非常短,提升开发效率。 13 | + 开发环境兼容 14 | J-Link 支持多种操作系统,包括 Windows, Linux, 和 macOS并且能够与 GDB 兼容。 15 | + 无缝集成和简单设置 16 | J-Link 只需插入设备并进行简单配置,即可开始调试。它提供了简洁的用户接口和广泛的在线资源,帮助初学者快速上手。 17 | + 免费软件工具 18 | SEGGER 提供了免费的软件工具,如 J-Flash, Ozone(调试器), J-Link RTT Viewer 等,这些工具与 J-Link 无缝集成,进一步增强了开发和调试的体验。 19 | + 高可靠性 20 | J-Link 的硬件设计坚固耐用,具有极高的可靠性和稳定性。它能够在长时间的调试过程中保持稳定,不会因长时间连接或高负载运行而出现故障。 21 | 连接过程: 22 | 1. 安装驱动程序和Ozone 23 | 下载J-Link和最新J-Link调试软件Ozone。 24 | [链接](https://www.segger.com/downloads/jlink/) 25 | 2. 连接硬件 26 | ,将Segger调试器连接至以下对应引脚,下图为JTAG接口示意图和连接示图。 27 | ![image](https://github.com/user-attachments/assets/e0cf6e28-525b-4cb7-8871-01361927a053) 28 | ![image](https://github.com/user-attachments/assets/074b50c6-c8a7-4eac-971b-5db2ec0ba8f5) 29 | 30 | 3. 连接 31 | 打开Ozone,创建Project,Device选择U74或S76,然后一直点击下一步,直到显示JLink Script File脚本的界面。 32 | ![image](https://github.com/user-attachments/assets/6605b026-211a-4dfa-80c9-e3bb9ad00a62) 33 | 34 | 选择U74 35 | 36 | ![image](https://github.com/user-attachments/assets/c407a6a9-087c-41b1-abb6-cc10a75766ea) 37 | 38 | 脚本[ConnectTAP1](https://gitlab.eduxiji.net/T202410011992734/project2210132-235708/-/blob/master/installation%20and%20usage/template_connecttap1.jlinkscript) 39 | 40 | #### 输出: 41 | 若输出如下即为正确 42 | ![b050e109d3c5b58ed7dde95b73316c4](https://github.com/user-attachments/assets/f6014f18-4e27-4757-a09b-30112b2b0070) 43 | 44 | 4. 调试 45 | 如果Ozone可以调试,开启JLinkGDBserverExe 46 | 47 | 48 | ### 问题及解决: 49 | 1. 找不到PC 50 | 51 | ![13bf8dab45f87e4dceaf96293a64bee](https://github.com/user-attachments/assets/732dc44e-8a45-4d90-b1b1-d42200787c1c) 52 | 53 | 54 | 将 initial PC 改为DO not set 55 | 56 | ![257ac54d9ee3f304bf66aaec8030cb0](https://github.com/user-attachments/assets/8694a588-53f0-4592-bb08-196a1f6afebe) 57 | 58 | 59 | 2. JLink正确链接,但Device未成功设置 60 | 61 | ![e83c78864ac2045dfdab9e961793c3a](https://github.com/user-attachments/assets/16aa4de4-840a-4d68-bba6-e7ec9fcbff3a) 62 | 63 | 64 | 确认做出如下设置 65 | 66 | ![04d03cba6ebd3441699e3ac8a013554](https://github.com/user-attachments/assets/7ed11c49-f9b5-4fdb-9bb6-ea2c6424ffe0) 67 | 68 | 切换到root下重试 69 | 70 | 3. JLink正确链接,Device成功设置,但GDB仍未连接 71 | 72 | ![a9a236dab09a29127064aaa6f3e97e5](https://github.com/user-attachments/assets/6ac13a1d-2acd-4fb0-8ef4-45268646bf50) 73 | 74 | GDB架构与JLink不兼容,切换gdb-multarch 75 | -------------------------------------------------------------------------------- /docs/周报/record_1/20240815-具体工作.md: -------------------------------------------------------------------------------- 1 | ![97b0d37bcdca54597c3101123baf6ab](https://github.com/user-attachments/assets/53224ca6-a49e-4fb5-801d-9512e1234705) 2 | 3 | ### 遇到的问题 4 | qemu虚拟机环境没用dcsr寄存器,板子上却有。 5 | 里面stepie字段可以控制单步的时候是否打开中断。 6 | 我们查看后发现stepie的值是0,那么单步的时候中断是关闭的,这个时候去单步一个会导致中断的指令无效。 7 | ### 尝试解决 8 | #### 修改csr 9 | 我们尝试修改后发现我们板子不支持调试器修改csr 10 | 如果调用openocd的set_reg命令修改dcsr寄存器值,不仅寄存器的值不会改变,而且还会出现一个提示,说正在关闭csr寄存器的写入功能。 11 | #### 更换边界断点位置 12 | ecall之后不会立马切换页表,我们尝试把边界断点设置到ecall中断的中断处理函数上面。用户态断点保存在我们设定的断点组里面也不会丢,操作系统页表刷新以后再把断点加回来。在我们这个os中,ecall的中断处理函数刚好在跳板页里,跳板页是不论内核态还是用户态都可以访问的,且不论内核态还是用户态,跳板页的虚拟地址都是一样的,所以这个思路是可行的。 13 | 现在的问题是,中断处理函数是写在trampoline.S这个汇编语言文件里的,GDB无法根据内核符号表定位到这个汇编文件,GDB根据内核符号表只能定位到c语言的源代码文件,奇怪的是,有一个用户态程序是直接由一个汇编代码文件编译生成,GDB却可以定位到。 14 | 我们尝试修改汇编器和链接器的编译参数都没用 15 | -------------------------------------------------------------------------------- /docs/周报/record_2/20241206-具体工作.md: -------------------------------------------------------------------------------- 1 | # 复现 2 | 3 | ### 遇到的问题及解决方案 4 | 5 | ### M1芯片UTM模拟X86_64 运行ubuntu24.04 LTS(曾小红) 6 | 7 | 由于我是模拟的x86架构,虚拟机的性能较差,于是我修改了安装脚本`test.sh`,并提交了修改,修改为:在make后面添加了`-j$(nproc)`选项,实现动态设置 make 的编译线程数,可尽可能的利用核心进行多线程编译。 8 | 9 | #### 1.运行test.sh,提示无法安装rust 10 | 11 | ![](./images/2024-11-29202614.png) 12 | 13 | 问题是安装脚本在非交互模式下运行,但它需要用户确认默认设置,可以使用 -y **参数自动接受默认选项**,在运行安装命令时,添加 -y 参数跳过交互确认,并指定安装`nightly`版: 14 | 15 | ```shell 16 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain nightly -y 17 | ``` 18 | 19 | 运行以下命令,让终端能够识别 Rust 的安装路径,这样才能查到rustc,cargo的版本: 20 | 21 | ```shell 22 | source $HOME/.cargo/env 23 | ``` 24 | 25 | #### 2.编译qemu-system-riscv64报错 26 | 27 | ![](./images/2024-12-06155429.png) 28 | 29 | ```shell 30 | error: storing the address of local variable 'slice' in '*ctx.bh_slice_list' [-Werror=dangling-pointer] 31 | ``` 32 | 33 | 可能是因为编译器版本或者环境差异,导致编译出现这个情况(我的编译器启用了 `-Werror`的选项,将代码中的警告视为致命错误,本质原因还是QEMU源代码有问题),这里的解决办法是在编译的时候启用` --disable-werror `参数禁止`-Werror` 34 | 35 | ```shell 36 | ./configure --target-list=riscv64-softmmu,riscv64-linux-user --disable-werror 37 | make -j$(nproc) 38 | sudo make install 39 | ``` 40 | 41 | 42 | 43 | #### 3.error[E0787]: the `asm!` macro is not allowed in naked functions 44 | 45 | 根据安装文档中编译rcore-ebpf部分的第四点,我将rustc更新到了较新的版本,进行编译的时候出现了禁止在裸函数中使用 asm! 宏的问题,然后我就将版本切换到了最开始报错要求更新rust版本的最低要求,即1.73.0-nightly: 46 | 47 | ![](./images/image-20241206201635589.png) 48 | 49 | 50 | 然后进行编译就成功了。 51 | 52 | 53 | ### 遇到的问题及解决方案(尹怡然) 54 | 55 | ##### **1.编译riscv工具链等待时间非常长,网络一波动就失败(主要问题还是在下载过慢方面,大多数时间都花在这里了)==已解决==** 56 | 57 | **解决问题方法:** 58 | 59 | > 本身win11的hyper V和vmare workstation有兼容性问题,正常来说,不能二者共存 60 | > 61 | > 需要在win11上流畅运行vmare虚拟机,需要在win11用管理员权限打开power shell 62 | > 63 | > 然后在里面运行命令: 64 | > 65 | > bcdedit /set hypervisorlaunchtype off 66 | > 67 | > powercfg /powerthrottling disable /path “C:\Program Files (x86)\VMware\VMware Workstation\x64\vmware-vmx.exe” 68 | > 69 | > “C:\Program Files (x86)\VMware\VMware Workstation\x64\vmware-vmx.exe” 改成你的系统的虚拟机路径 70 | > 71 | > 就OK了。 72 | > ———————————————— 73 | > 74 | > 原文链接: 75 | 76 | 77 | 78 | 79 | 80 | ##### **2.网络连接问题又出现,网络图标消失 ==已解决==** 81 | 82 | 解决方法: 83 | 84 | 和第一周出现的问题解决方法一样,network manager解决 85 | 86 | 87 | 88 | 89 | 90 | **3.test.sh安装有python支持的riscv工具链时克隆git仓库失败==已解决==** 91 | 92 | 解决方法: 93 | 94 | **`fatal: destination path 'riscv-gnu-toolchain' already exists and is not an empty directory.`** 95 | 96 | ./test.sh前已经装了toolchain,导致不需要再git clone,脚本识别没有git clone就直接跳到克隆失败 97 | 98 | 删掉**`path 'riscv-gnu-toolchain'`**让脚本装就好了 99 | 100 | 101 | 102 | 103 | 104 | **4.the asm!\* macro is not allowed in naked functions==已解决?==** 105 | 106 | ![image.png](https://note.youdao.com/yws/res/f/WEBRESOURCEa258069435d1123921344a9f3f28af9f) 107 | 108 | 编译器升级导致asm这个宏不可用了,自行修改这行代码后成功 109 | -------------------------------------------------------------------------------- /docs/操作系统大赛参赛文档/决赛一阶段文档.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/docs/操作系统大赛参赛文档/决赛一阶段文档.pdf -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | code-debug 项目 9 | 10 | 11 | 25 | 26 | 27 |
28 | 29 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /installation and usage/硬件配置与调试.md: -------------------------------------------------------------------------------- 1 | 对应的40 Pin引脚 2 | 3 | ![pin引脚](https://github.com/user-attachments/assets/0209cef1-0a7b-4422-963c-12cd262f4fb1) 4 | 5 | 将Segger调试器连接至以下对应引脚,下图为JTAG接口示意图和连接示 6 | 图。 7 | ![JTAG](https://github.com/user-attachments/assets/10588266-3dc6-4aec-9171-0e63416849ce) 8 | 9 | ![连接示意图](https://github.com/user-attachments/assets/441729bb-939c-4c82-a3a5-74076830bbdc) 10 | 11 | #### 安装JLink 12 | 在[这里]( https://www.segger.com/downloads/jlink/)下载JLink驱动 13 | 14 | ### 安装OpenOCD 15 | #### 安装libusb 16 | 在 [这里](https://github.com/libusb/libusb/releases)下载libusb源代码包,按照里面INSTALL文件安装libusb 17 | 18 | #### OpenOCD 19 | ```ts 20 | cd riscv-openocd 21 | ./bootstrap 22 | ./configure --enable-verbose --enable-ftdi --enable-stlink --enable-ft232r --enable-ftdi-cjtag --enable-jtag_vpi --enable-jtag_dpi --enable-openjtag --enable-jlink --enable-cmsis-dap --enable-nulink 23 | ``` 24 | configure过程中可能会提示缺失某些驱动。在包管理器里搜索驱动名字,通常能找到libxxx-dev。如果提示缺失libjaylink请跳转到第三步,安装好jaylink之后再继续第二步 25 | ```ts 26 | make 27 | sudo make install 28 | ``` 29 | 30 | #### libjaylink 31 | ```ts 32 | cd riscv-openocd/src/jtag/drivers/libjaylink 33 | sudo apt install automake autoconf libtool pkg-config 34 | ./autogen.sh 35 | ./configure 36 | make 37 | sudo make install 38 | ``` 39 | ### 进行调试 40 | 41 | 1. 连接JLink和串口 42 | 2. 打开调试器 43 | 3. 按重置按钮三秒后松开 44 | 4. 在任务管理器里关掉tmux(如果有的话) 45 | 5. 在vscode里开始调试(按f5) 46 | ### 编译 47 | 48 | 1. make clean 49 | 2. make hardcoded_ramdisk 50 | 3. make 51 | -------------------------------------------------------------------------------- /pre-record/2023-01-02-rcore-Tutorial-ebpf复现文档.md: -------------------------------------------------------------------------------- 1 | # musl 环境变量 2 | 3 | > You may need to install toolchains from musl.cc ... and add them to your PATH. 这一步可能写详细一 4 | > 点比较好,像这样: 5 | 6 | 下载 `riscv64-linux-musl-cross.tgz` 并解压,将`riscv64-linux-musl-cross/bin` 加入环境变量 7 | 8 | # cc 相关错误 9 | 10 | cmake 报错/usr/bin/cc 无法编译一个测试程序。运行的时候将 CC 变量指向`riscv64-linux-musl-gcc` 即可: 11 | 12 | `CC=riscv64-linux-musl-gcc make run` 13 | 14 | # #![feature(map_first_last)] 15 | 16 | 依照编译器提示修改之后即可顺利运行 17 | 18 | ```plain 19 | error[E0658]: use of unstable library feature 'map_first_last' 20 |   --> src/probe/arch/riscv/breakpoint.rs:44:29 21 |    | 22 | 44 |         let addr = free_bps.pop_first().unwrap(); 23 |    |                             ^^^^^^^^^ 24 |    | 25 |    = note: see issue #62924 for more information 26 |    = help: add `#![feature(map_first_last)]` to the crate attributes to enable 27 | ``` 28 | -------------------------------------------------------------------------------- /pre-record/2023-02-13.md: -------------------------------------------------------------------------------- 1 | ### 20230213 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 制定[学期计划](https://shimo.im/docs/8Nk6MDERPKfNE8qL#anchor-OChJ) 6 | 2. 完善 kprobe,符号表支持基本有了,还在 debug 7 | 1. 用内嵌汇编开辟一个内存块 8 | 2. 编译时用 `nm` 提取出符号表(utf-8) 9 | 3. 编译后在内存块中注入符号表信息 10 | 4. 测试(还没弄) 11 | 12 | #### 下周工作 13 | 14 | 3. 继续完善 kprobe 15 | 4. 论文翻译 16 | -------------------------------------------------------------------------------- /pre-record/2023-02-20.md: -------------------------------------------------------------------------------- 1 | ### 20230220 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. kprobe 符号表支持已经完成 6 | 1. 在 os 阶段就先注入,这个方案可行 7 | 2. 直接跑 os 文件能启动,但是用户程序无法执行 8 | 3. 最好的方案是 split-debuginfo 参数,但是经过实际测试,它不支持 9 | 4. 好工具:rustfilt 10 | 2. 看 uprobe 代码 11 | 12 | #### 下周工作 13 | 14 | 1. 优先解决对 eBPF 以外的符号信息的依赖; 15 | 2. uprobe-crate(问 pcy) 16 | 3. backtrace,问群里有没人做 17 | 4. 参数-多用户进程 18 | 5. 移植文档 19 | 6. 翻译论文 20 | -------------------------------------------------------------------------------- /pre-record/2023-03-02.md: -------------------------------------------------------------------------------- 1 | ### 20230302 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 优先解决对 eBPF 以外的符号信息的依赖; 6 | 1. sys_open 之外的系统调用都没这个问题 7 | 2. uprobe 做成 crate 8 | 1. 问了彭淳毅,他说: 9 | 1. uprobe 和 os 的耦合程度很大,没法做成 crate 10 | 2. 他的 uprobe 和这个 kprobe 不兼容 11 | 2. 因此我在读相关代码,希望至少能复用一些代码片段 12 | 3. 看 ftrace 相关的资料,希望做 backtrace 13 | 1. mcount 14 | 4. 写移植文档: 15 | [https://github.com/chenzhiy2001/code-debug/blob/master/docs/port.md](https://github.com/chenzhiy2001/code-debug/blob/master/docs/port.md) 16 | 5. 翻译论文 17 | 18 | #### 下周工作 19 | 20 | 1. 参数 21 | 2. 问路博雅 22 | 3. 翻译论文 23 | -------------------------------------------------------------------------------- /pre-record/2023-03-09.md: -------------------------------------------------------------------------------- 1 | ### 20230309 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. backtrace 6 | 1. 开启 mcount 7 | 2. 写 ebpf 程序,打印返回值(暂不放到 map 里) 8 | 3. kretprobe -> mcount ,则可以得知返回地址.(这是绕弯的做法,而且有时可能不管用. 接下来需要弄清 9 | 楚 mcount 做了什么) 10 | 11 | #### 下周工作 12 | 13 | 1. 哪些是依赖,哪些是参数 14 | -------------------------------------------------------------------------------- /pre-record/2023-03-16.md: -------------------------------------------------------------------------------- 1 | ### 20230316 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 修改了 [port.md](https://github.com/chenzhiy2001/code-debug/blob/master/docs/port.md) 明确了哪些 6 | 是依赖,哪些是配置 7 | 1. 希望在毕设结束时能给出两个 Rust OS 的跟踪配置,并演示跟踪过程; 8 | 2. 写了一个例子:用户输入要跟踪的函数名,然后执行一些操作,然后查看跟踪记录. 遇到的问题: 9 | 1. userlib 没提供 scanf,无法输入. 10 | 2. Shell 不支持命令行参数 11 | 3. 用于显示跟踪记录的程序本身也会触发插跟踪功能. 12 | 4. 需要用 eBPF 程序写一个 GDB Server,并形成文档; 13 | 14 | #### 下周工作 15 | 16 | 1. 写一个文档描述调试工具的架构 17 | 2. 参考[一个简单的 gdbserver 的实现](https://github.com/bet4it/gdbserver/blob/master/gdbserver.c)用 18 | ebpf 程序写一个 GDB Server 19 | 3. 翻译论文 20 | -------------------------------------------------------------------------------- /pre-record/2023-03-23.md: -------------------------------------------------------------------------------- 1 | ### 20230323 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 准备毕设开题报告和 OSATC 的报告 6 | 2. 看 gdb 和 gdbserver 通信 7 | 的[协议](https://sourceware.org/gdb/onlinedocs/gdb/Overview.html#Overview) 8 | 3. 写 eBPF 版的 virtio-net[驱动](https://github.com/rcore-os/virtio-drivers)(还没弄明白) 9 | 10 | #### 下周工作 11 | 12 | 1. 用串口 13 | -------------------------------------------------------------------------------- /pre-record/2023-03-30.md: -------------------------------------------------------------------------------- 1 | ### 20230330 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 多个串口是可行的, `UART1` 地址就是 0x1000_1000,只是很多资料没说这事 6 | (rCore-Tutorial[对应的章节](https://rcore-os.cn/rCore-Tutorial-Book-v3/chapter9/2device-driver-1.html)也 7 | 没说这事,qemu 源码里也不容易直接看出来),最后居然是 chatGPT 给了点提示才找到的 8 | ([基于 qemu-riscv 从 0 开始构建嵌入式 linux 系统 ch3. 添加中断控制器、串口、pflash 支持](https://blog.csdn.net/weixin_39871788/article/details/118615530)) 9 | 。 10 | 2. 但是 rCore-ebpf 的串口还是用 RustSBI 实现的,不支持多串口。因此我把和串口有关的代码复制过去,结果 11 | 所有的应用程序都无法执行了,排查后发现是 rcore-ebpf 和新 rCore-Tutorial 都修改了中断处理的代码, 12 | 因此产生了冲突,简单画个图大概像这样: 13 | 14 | ```plain 15 | ______rcore-ebpf(modified trap handling) 16 | / | 17 | / | conflicts 18 | / | 19 | old rCore(use RustSBI for UART)-----------new rCore(handles UART by itself, also modified trap handling) 20 | ``` 21 | 22 | 这个有点麻烦,搞了好几天都没解决。主要的问题是 1)新 rCore 用了信号机制 2) `UPSafeCell` 。 23 | 24 | 3. 目前可以工作的部分:gdb 连串口,qemu 提供多串口,ebpf 收发串口消息的帮助函数。 25 | 1. 目前 eBPF 还不能真正进行串口收发; 26 | 4. 如果不修改内核,串口驱动完全用 eBPF 实现的话,会有个问题:串口驱动涉及中断,因此必须在中断处理例 27 | 程里设置断点,但是断点本身也会触发中断处理例程,因此会进入死循环。这条路也走不通。 28 | 1. eBPF 依赖的内核模块是不能自己调试的; 29 | 2. eBPF 的调试依赖内核的两个串口; 30 | 31 | #### 下周工作 32 | 33 | 5. 继续多串口支持; 34 | 6. 升级 rCore 的版本; 35 | -------------------------------------------------------------------------------- /pre-record/2023-04-06.md: -------------------------------------------------------------------------------- 1 | ### 20230406 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 串口还是不行,[官方文档](https://www.qemu.org/docs/master/system/riscv/virt.html)显示只支持一个串 6 | 口 7 | 2. eBPF 会 SegFault 8 | 3. eBPF 和 QEMU 中的 GDB server 的区别: 9 | 1. 控制能力 10 | 2. 监测能力 11 | 12 | #### 下周工作 13 | 14 | 4. ,向勇协调外部帮助; 15 | 5. 找尤予阳帮助解决串口访问问题; 16 | 6. 分析不同 GDB server 的能力区别; 17 | 7. 开始写 eBPF 中的 GDB server; 18 | -------------------------------------------------------------------------------- /pre-record/2023-04-13.md: -------------------------------------------------------------------------------- 1 | ### 20230413 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 将 ebpf 升级到新版本 rCore-Tutorial 6 | 2. 支持多串口,能读和写单个字符(1000_1000 被 gpu buffer 给占用了,我换了个地址.) 7 | 1. 关于 qemu 的启动参数 8 | :[https://mail.gnu.org/archive/html/qemu-discuss/2012-04/msg00002.html](https://mail.gnu.org/archive/html/qemu-discuss/2012-04/msg00002.html) 9 | 2. 第二个串口的 PLIC 中断无法触发,改为轮询 10 | 3. 有个 bug:连续读和写交错的话会冲突(可能是轮询导致的),所以没法写一个回显程序(loopback)(“ 11 | 复读机”)方便地调 gdb 12 | 3. 写了 eBPF 和 gdb 区别 13 | 的[文档](https://github.com/chenzhiy2001/code-debug/blob/master/docs/ebpf%20vs%20ptrace.md) 14 | 1. eBPF 的 gdbserver 只有强的动态跟踪能力; 15 | 2. 控制只能通过 QEMU 的 gdbserver 来实施; 16 | 4. gdbserver 在调 17 | 1. 可以考虑在 VF2 开发板做 Rust 写的 OS 上进行内核实现和 eBPF 的功能演示; 18 | 19 | #### 下周工作 20 | 21 | 5. 完善 QEMU 和 SBI 中的多串口支持,以实现多串口的数据收发; 22 | 6. 操作系统比赛报名; 23 | 7. 实现一个支持最小要求(能读寄存器和内存 24 | 。[官方文档](https://sourceware.org/gdb/onlinedocs/gdb/Overview.html#Overview))的 gdbserver 25 | 1. 一个大致的框架,描述什么功能需要,什么不需要(包括标准的和非标准的),按重要性排序 26 | -------------------------------------------------------------------------------- /pre-record/2023-04-20.md: -------------------------------------------------------------------------------- 1 | ### 20230420 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 根据赵方亮学长给的[链接](https://gallium70.github.io/rv-n-ext-impl/ch3_2_bootloader.html)找到了线 6 | 索,修改了 sbi 的 pmp 设置,实现了基于中断的多串口数据收发,可以正常收发字符串。 7 | 2. 写了 gdbserver,能正常收发包 8 | ([packet](https://sourceware.org/gdb/current/onlinedocs/gdb.html/Overview.html#Overview)) 9 | 。[参考文档](https://medium.com/@tatsuo.nomura/implement-gdb-remote-debug-protocol-stub-from-scratch-2-5e3025f0e987) 10 | 3. 实现寄存器数据获取这个地方有些疑惑,因为 gdb 的断点查看指令查看的是当前的寄存器值,eBPF 做不到这 11 | 一点(因为要先插桩。就算不插桩,弄一个“立即执行本 eBPF 程序”的系统调用也是没意义的,这样获取到的 12 | 是系统调用时刻的寄存器值)。因此要结合 qemu 的 gdbserver。但是怎么结合还没想清楚。因为 gdb 不能同 13 | 时连两个 gdbserver。也不可能让虚拟机里的内核来控制虚拟机。改 qemu 的 gdbserver 的话,就违背了我们 14 | 的初衷(在真实硬件上也能方便跟踪)了。 15 | 1. 内存信息也同理 16 | 4. 不知道队名叫啥 17 | 18 | #### 下周工作 19 | 20 | 5. 结合两个 gdbserver:描述用一个 VScode 同时连接被跟踪操作系统的 OpenOCD 和 eBPF 的实施方案; 21 | 6. 报名 22 | 7. 给一个到写出文章为止的计划; 23 | -------------------------------------------------------------------------------- /pre-record/2023-04-27.md: -------------------------------------------------------------------------------- 1 | ### 20230427 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 根据赵方亮学长给的[链接](https://gallium70.github.io/rv-n-ext-impl/ch3_2_bootloader.html)找到了线 6 | 索,修改了 sbi 的 pmp 设置,实现了基于中断的多串口数据收发,可以正常收发字符串。 7 | 2. 写了 gdbserver,能正常收发包 8 | ([packet](https://sourceware.org/gdb/current/onlinedocs/gdb.html/Overview.html#Overview)) 9 | 。[参考文档](https://medium.com/@tatsuo.nomura/implement-gdb-remote-debug-protocol-stub-from-scratch-2-5e3025f0e987) 10 | 3. 实现寄存器数据获取这个地方有些疑惑,因为 gdb 的断点查看指令查看的是当前的寄存器值,eBPF 做不到这 11 | 一点(因为要先插桩。就算不插桩,弄一个“立即执行本 eBPF 程序”的系统调用也是没意义的,这样获取到的 12 | 是系统调用时刻的寄存器值)。因此要结合 qemu 的 gdbserver。但是怎么结合还没想清楚。因为 gdb 不能同 13 | 时连两个 gdbserver。也不可能让虚拟机里的内核来控制虚拟机。改 qemu 的 gdbserver 的话,就违背了我们 14 | 的初衷(在真实硬件上也能方便跟踪)了。 15 | 1. 内存信息也同理 16 | 4. 不知道队名叫啥 17 | 18 | #### 下周工作 19 | 20 | 5. 结合两个 gdbserver:描述用一个 VScode 同时连接被跟踪操作系统的 OpenOCD 和 eBPF 的实施方案; 21 | 6. 报名 22 | 7. 给一个到写出文章为止的计划; 23 | -------------------------------------------------------------------------------- /pre-record/2023-05-04.md: -------------------------------------------------------------------------------- 1 | ### 20230504 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 目前能够实现通过 gdb 连接 os 里的 ebpf server,然后设置断点。断点触发之后 eBPF 程序收集寄存器信息 6 | 并返回给 gdb。流程走通了,不过文本的格式还很难看 7 | 1. commit: 8 | 1. [https://github.com/chenzhiy2001/rcore-ebpf/commit/4dc957cc8ca4e1343ca3c6df31e9ba6ecf583cbe](https://github.com/chenzhiy2001/rcore-ebpf/commit/4dc957cc8ca4e1343ca3c6df31e9ba6ecf583cbe) 9 | 2. [https://github.com/chenzhiy2001/uCore-Tutorial-Test-2022A/commit/89ace80e92463ec656d51a42800114fbc0dfaadb](https://github.com/chenzhiy2001/uCore-Tutorial-Test-2022A/commit/89ace80e92463ec656d51a42800114fbc0dfaadb) 10 | 11 | #### 下周工作 12 | 13 | 2. 在 VSCode 结合 gdbserver 和 eBPF 14 | 3. 信息获取能力增强:uprobe、函数调用栈(参数和返回值=>火焰图等信息展示)、异步函数调用栈;在真板子 15 | 上获取信息; 16 | -------------------------------------------------------------------------------- /pre-record/2023-05-11.md: -------------------------------------------------------------------------------- 1 | ### 20230511 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 在 VSCode 结合 gdbserver 和 eBPF。现在二者可以同时使用 6 | 。[commit](https://github.com/chenzhiy2001/code-debug/commit/47252f5c2f61596e99d97615431f2237fd2b748a) 7 | 1. 可以同时从 QEMU 的 GDB 和系统内的 eBPF 获取跟踪信息; 8 | 2. 主要的工作是将用于和 eBPF server 通信的 gdb 脚本改成 MI 协议的。还有就是很多字符串的错误处理( 9 | 比如字符串末尾有 `\0` 会导致 gdb 报错)。 10 | 3. UI 方面,本来写了个简单的 WebView,但是使用起来不灵活,开发上 VSCode 给的消息传递的 API 用起来 11 | 很繁琐,所以目前先用 VSCode 的调试控制台 12 | 13 | #### 下周工作 14 | 15 | 2. 写论文: 16 | 1. 5 月 20 号提交完整论文; 17 | 2. 5 月 24 号答辩; 18 | 3. 论文初稿上传 Github,周末向老师意见 19 | 3. 信息获取能力增强:uprobe、函数调用栈(参数和返 回值=>火焰图等信息展示)、异步函数调用栈;在真板子 20 | 上获取信息;(后续工作:选项) 21 | 4. 断点和插桩自动选择 22 | -------------------------------------------------------------------------------- /pre-record/2023-05-18.md: -------------------------------------------------------------------------------- 1 | ### 20230518 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 写论文([链接](https://github.com/chenzhiy2001/code-debug/blob/master/docs/thesis.md))。最后三小 6 | 节("eBPF Server 案例"、"在 VSCode 界面中适配 eBPF Server"、"总结与展望")还没写完,其它都写完了 7 | 。案例打算展示系统调用插桩和系统调用参数获取(因为系统调用的参数似乎不会放到栈上,直接读寄存器就 8 | 行)。涉及 eBPF Server 的两张图没画。 9 | 10 | #### 下周工作 11 | 12 | 1. 赶快写完,给吴老师和向老师审核,根据反馈的意见再修改 13 | 1. 需要填充大量字数。可以加:debug ui(webview 和后面新的界面),ebpf 移植工作,基于中断、MMIO 的 14 | 串口原理。 15 | 2. 相关工作可以加:qemu. gdb, debug adapter,ebpf,kprobe uprobe, rsp,mi,rust(宏,lazy 16 | static),llvm,dwarf,riscv 17 | 2. 改任务书,向系统内添加周记 18 | 3. 案例可以写特权级指令,捕获条件由 ebpf 做,跟踪由 gdb 做(因为 ebpf 不能跟踪特权级指令)。 19 | 4. 翻译 20 | -------------------------------------------------------------------------------- /pre-record/2023-05-25.md: -------------------------------------------------------------------------------- 1 | ### 20230525 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 完成论文答辩 6 | 7 | #### 下周工作 8 | 9 | 1. 在一周内在仓库中完成整理论文结果; 10 | -------------------------------------------------------------------------------- /pre-record/2023-06-01.md: -------------------------------------------------------------------------------- 1 | ### 20230601 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 整理了在线版本的论文([链接](https://chenzhiy2001.github.io/code-debug-doc/index.html)),还加了 6 | 个评论区 7 | 8 | #### 下周工作 9 | 10 | 1. 加文献翻译,布署指南 11 | 2. 给出写出文章前的安排 12 | 3. 毕设收获和改进 13 | 4. 准备报告 14 | -------------------------------------------------------------------------------- /pre-record/2023-06-08.md: -------------------------------------------------------------------------------- 1 | ### 20230608 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 加[文献翻译](https://chenzhiy2001.github.io/code-debug-doc/_downloads/2216d21188182b19b0c52adc60d48c33/%E9%99%88%E5%BF%97%E6%89%AC-%E8%AE%BA%E6%96%87%E7%BF%BB%E8%AF%91.pdf),[部署指南](https://chenzhiy2001.github.io/code-debug-doc/index.html#id2) 6 | 2. 给出写出文章前的安排 7 | 1. 尝试跟踪异步函数 8 | 2. 完善函数参数的获取(栈) 9 | 3. 在真实硬件上运行(向驹韬) 10 | 4. uprobe 有点难,作为可选项 11 | 3. 写毕设收获和改进([链接](https://chenzhiy2001.github.io/code-debug-doc/appendix-b/index.html)) 12 | 1. 兴趣、表达能力、 13 | 4. 改 code-debug 的 bug 14 | 15 | #### 下周工作 16 | 17 | 1. 准备报告 18 | -------------------------------------------------------------------------------- /pre-record/2023-06-15.md: -------------------------------------------------------------------------------- 1 | ### 20230615 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 完成调试器和 rCore-Tutorial-v3 的行号解耦工作(适配 rCore-N 不需要文件名的解藕 6 | )[commit](https://github.com/chenzhiy2001/code-debug/commit/03904dbc598efe2cb3411cdc21bb98b86412f7bf) 7 | 1. 一个好消息是 VSCode 现在提供了直接读取、修改 launch.json 配置文件的 API 了 8 | ([链接](https://stackoverflow.com/questions/65520829/get-launch-configurations-from-vscode-extension)) 9 | 。因此,未来可以把所有的配置都集中到这一个配置文件里。 10 | 2. 尝试 debug rCore-N 中的异步函数。根据 readme 安装了 `just` 和修改版 qemu,但是 rCore-N 运行不起来 11 | 。重复报错 `cannot find value RTS_PULSE_WIDTH in this scope` 12 | 3. 学习了异步函数的机制。主要 13 | 是[这份资料](https://tony612.github.io/tokio-internals/01_intro_async.html)。我想到 gdb 里有一个 14 | 同时调试两个线程的模式(叫 non-stop mode),能不能借来用。一个“线程”是 os,另一个“线程”是调度 15 | Futures 的例程。这样,异步 Future 的依赖关系就转换成线程间的资源依赖关系来处理。 16 | 1. 此 17 | 外[stackoverflow 上](https://stackoverflow.com/questions/63488379/how-can-i-set-a-breakpoint-in-an-async-function)也 18 | 有一个调试 async 函数的方案。不知道行不行。 19 | 4. 尝试把 latex beamer 转成 ppt,没弄出来。主要是两个原因: 20 | 1. PPT 和 latex 的字体渲染和排版算法很不一样。 21 | 2. latex beamer 用了 PowerPoint 里没有的中文字体 Fandol。Fandol 在 PowerPoint 里非常丑。 22 | 23 | #### 下周工作 24 | 25 | 1. 断点组模块有个小 bug 导致又不能从用户态回到内核态了,要修一下 26 | 2. uprobe 的模块化; 27 | -------------------------------------------------------------------------------- /pre-record/2023-06-23.md: -------------------------------------------------------------------------------- 1 | ### 20230623 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 制定 [时间表](https://shimo.im/docs/e1AzdDXvZBC6l6qW)。主要工作是:uprobe,获取栈上信息,修 bug, 6 | 写文章。 7 | 2. 读完了彭淳毅的文档。 8 | 1. [这里](https://github.com/hm1229/rCore-ebpf/blob/master/docs/sys_impl/probes.md)描述了需要实现 9 | 的 uprobe API。 10 | 2. [这里](https://github.com/hm1229/rCore-ebpf/blob/master/docs/sys_design/uprobes.md)描述了大致 11 | 的代码实现。 12 | 3. 他没画 Uprobes 的流程图,但是画了 Kprobes 的 13 | ([链接](https://github.com/hm1229/rCore-ebpf/blob/master/docs/sys_design/kprobes.md)),大致 14 | 描述了需要实现的数据结构和一些重要的处理流程。 15 | 4. [这里](https://github.com/hm1229/rCore-ebpf/blob/master/kernel/src/kprobes/uprobes.rs)是 16 | uprobe 的主体代码,应该可以抄一部分。 17 | 3. 问了彭淳毅本人,他说主要难点在于 uprobes 要改页表。因此得复习一下页表的知识。 18 | 4. 研读了石尚锋学长的 [async 函数跟踪总结](https://cubele.github.io/probe-docs/async-probe/) 。结论 19 | 是:如果我们能做好栈帧的解析,有完善的 stacktrace 功能的话,就可以尝试跟踪正在执行的 async 函数。 20 | 其他的工作有点复杂,就先不弄了。 21 | 5. 各种资料都读完了,但是不知道从哪下手。 22 | 6. 由于我之前的失误,上周的解构工作的代码有错误,造成调试器完全不可用,代码 23 | ([commit](https://github.com/chenzhiy2001/code-debug/commit/225f4e3ba188ce06ba731262c7f41e0a569952aa)) 24 | 和文档 25 | ([commit](https://github.com/chenzhiy2001/code-debug/commit/f394e858058bf294db1205f6a948dc79fe0f891f)) 26 | 已经更正。 27 | 7. 参加完毕业典礼,搞各种手续,搬宿舍 28 | 8. 可能的创新: 29 | 1. 用户态与内核态切换:特权级切换跟踪; 30 | 2. 多个用户态与内核态切换:uprobe 模块化; 31 | 3. 对真实服务系统的跟踪:qemu 与 eBPF 的结合; 32 | 4. 多种 Rust OS 的适配:模块化、rCore、AlienOS、 33 | 34 | #### 下周工作 35 | 36 | 1. uprobe 的模块化;(用#[cfg(rCore-Tutorial)]) 37 | 1. 需要先问下彭淳毅怎么复现 38 | 2. 写小论文大纲; 39 | -------------------------------------------------------------------------------- /pre-record/2023-06-29.md: -------------------------------------------------------------------------------- 1 | ### 20230629 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 利用 rust 的 `#[cfg(feature="rCore-Tutorial")]` 记号做条件编译,从而写出一个 uprobe 模块 6 | [https://github.com/chenzhiy2001/ruprobes](https://github.com/chenzhiy2001/ruprobes) 7 | 1. 这个工作还没有完成; 8 | 2. 需要测试在多进程环境下的跟踪功能; 9 | 1. 边界断点要识别即将进入的用户态程序 10 | 2. 在 rCore-Tutorial 中适配 uprobe 模块。剩下一些和 rCore-Tutorial 耦合度比较高的代码还没写。 11 | - [ ] 在 ebpf 代码中注册 uprobe( `uprobe_register` ) 12 | - [ ] `uprobe_handler` 13 | - [ ] `uprobe_unregister` 14 | - [ ] 页表操作 15 | - [x] 在 sys_exec 系统调用中初始化 uprobe 16 | - [x] 修改中断处理例程 17 | 18 | #### 下周工作 19 | 20 | 1. 完成 uprobe 的模块化 21 | 2. 写论文提纲 22 | 1. 结合论文写作进行文献阅读; 23 | -------------------------------------------------------------------------------- /pre-record/2023-07-05.md: -------------------------------------------------------------------------------- 1 | ### 20230705 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. uprobe 的模块化剩下页表操作的一小部分代码没写完(其他地方基本都缝合上了,但是因为页表这部分还没写 6 | 完,所以没法编译验证是否有 bug)。 7 | 1. 问了彭淳毅,他说他当时找了半天没找到 get_new_page 函数在 rCore-Tutorial 中的对应,我再找了找, 8 | 确实没有,只能自己补充。 9 | 2. 在 rCore-Tutorial 的进程控制块中添加了进程名,并修改了相关的系统调用,写 10 | 了[文档的草稿](https://shimo.im/docs/8Nk6eRvV8os82lqL)。这个草稿还没把相关的代码加进去,加进去之 11 | 后会传到 github 仓库。 12 | 3. 调试器在向驹韬同学的电脑上没法运行,排查了半天发现一个比较隐蔽的 bug,在断点组切换的时候,如果用 13 | 户态断点无法设置(即报错 cannot access memory)gdb 会跳过这些断点的设置,但是不会完全跑飞,内核态 14 | 断点仍然可以用。 15 | 16 | #### 下周工作 17 | 18 | 1. 查 BUG; 19 | 2. 完成 uprobe 的模块化 20 | 3. 完成栈上的参数获取 21 | 4. 写论文提纲 22 | -------------------------------------------------------------------------------- /pre-record/2023-07-07-修正文档.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/2023-07-07-修正文档.pdf -------------------------------------------------------------------------------- /pre-record/2023-07-09.md: -------------------------------------------------------------------------------- 1 | 1. 旧版本的 trap-frame 不能用了,发现这个库已经更新,故换新版本 2 | 2. 将 get_exec_path,set_writeable,get_new_page 移到内核中。uprobe crate 中只留这三个函数的函数签名 3 | .代价是加了一堆 unsafe.... 4 | 3. ruprobes 库编译通过了,开始修内核的 bug 5 | 4. &str 会导致要添加一大堆 lifetime specifier, 考虑到我只是存软件所在的目录,占用空间很小,故改用 6 | String. 7 | 5. 内核也引入了 trapframe 库。 8 | -------------------------------------------------------------------------------- /pre-record/2023-07-12.md: -------------------------------------------------------------------------------- 1 | 1. 发现 vscode 的终端比 ubuntu 自带的好用,`ctrl+点击出现编译错误的文件名` 即可跳转到对应文件。唯一 2 | 的缺点就是卡了点。 3 | 2. handler 函数指针老是报错, 4 | 5 | ``` 6 | | |________^ doesn't have a size known at compile-time 7 | | 8 | = help: within `spin::mutex::Mutex<(dyn for<'r> FnMut(&'r mut UserContext) + Send + 'static)>`, the trait `Sized` is not implemented for `(dyn for<'r> FnMut(&'r mut UserContext) + Send + 'static)` 9 | ``` 10 | 11 | 得问彭淳毅。 12 | -------------------------------------------------------------------------------- /pre-record/2023-07-13.md: -------------------------------------------------------------------------------- 1 | ### 20230713 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. ruprobe 库现在能过编译了,但是内核有一个地方老是过不了编译,网上也没资料,这个地方编译时报错,错 6 | 误信息的大概意思是无法确定这个类型占用的空间,但是这个类型是由一些基本类型组成的,按常理来说不应 7 | 该出现这个错误的。 8 | 2. 建议好好写开发日志; 9 | 10 | #### 下周工作 11 | 12 | 1. 改进 ruprobe; 13 | 2. 开始写文章; 14 | -------------------------------------------------------------------------------- /pre-record/2023-07-16.md: -------------------------------------------------------------------------------- 1 | 1. 之前由于 rust-analyzer 没法正常分析 ruprobe 库相关的内容,所以没有指出代码中大量所有权相关的错误 2 | 。把这些错误(大概十几个)全都解决了。 3 | 2. 然后内核编译能过了....牛 4 | 3. 运行的时候,能显示 app_list,说明内核正常启动了,但是 panic 了 5 | :`[ERROR] [kernel] Panicked at src/sync/up.rs:111 already borrowed: BorrowMutError`本来想用自己的 6 | 调试器来调试这个内核,但是发现底下给出了 backtrace,所以可能直接看 backtrace 方便。 7 | 4. 下载了一个开源的 GUI ELF Viewer: XElfViewer,比 objdump readobj 方便些。 8 | 5. 看不出问题所在。还是用调试器吧....这工具自举了也挺好的..... 9 | -------------------------------------------------------------------------------- /pre-record/2023-07-19.md: -------------------------------------------------------------------------------- 1 | 1. 打算先换个角度。虽然内核和 uprobe 模块编译能过,但是有大量 warning. 我应该先把 warning 都消掉。 2 | 2. 发现大部分 warning 都不是我干的,都是前人的代码...一部分是保留一些后续工作的接口,一部分是为了调 3 | 试方便,多加了 mut 关键字。还有一部分是没用的 import,这些我给去掉了。 4 | 3. 由于错误信息并未告知准确的出错代码位置,我只能多加一些 Print 来看看。好在 print 还是能正常运作的 5 | 。 6 | 4. 由于 fs_list_apps()函数正常输出了磁盘中的应用程序列表,所以我从这个函数之后的一个函数 7 | add_initproc()开始调试。add_initproc()经过测试没有问题: 8 | 9 | ```rust 10 | fs::list_apps(); FINISHED 11 | Will do 12 | let _initproc = INITPROC.clone(); 13 | 14 | Done 15 | let _initproc = INITPROC.clone(); 16 | ``` 17 | 18 | - 注意到内核主函数里有行:`*DEV_NON_BLOCKING_ACCESS.exclusive_access() = true;`这个在旧版本的 19 | rCore-Tutorial 里没有的,而且这里用到了报错的 sync 的 exclusive_access 函数。如果是这里出了错,那 20 | 可能解决起来比较容易。加 print 看看。 21 | - 不妙,错误不在这里。错误在`task::run_tasks();`里. 22 | 23 | ```rust 24 | will gain DEV_NON_BLOCKING_ACCESS 25 | 26 | 27 | DEV_NON_BLOCKING_ACCESS gained 28 | ``` 29 | 30 | - 在 run_task 里,添加输出: 31 | 32 | ```rust 33 | pub fn run_tasks() { 34 | loop { 35 | println!("START"); 36 | let mut processor = PROCESSOR.exclusive_access(); 37 | println!("END"); 38 | ``` 39 | 40 | 结果很有趣,循环前两次是成功的,第三次失败了: 41 | 42 | ```shell 43 | START 44 | END 45 | START 46 | END 47 | [ERROR] [kernel] Panicked at src/sync/up.rs:111 already borrowed: BorrowMutError 48 | ``` 49 | 50 | 经过反复尝试,错误出现在`__switch`函数上,但是,\_\_switch 函数是用汇编写的,何来的 borrow? 换个角度 51 | ,可能是 uprobe 库里面添加了不必要的 exclusive_access()方法调用。来找找看。 52 | 53 | 我确实在 get_exec_path, get_new_page, set_writeable 函数中加了 exclusive_access()方法调用。然后谷歌 54 | 搜了下,那个错误是由于已经被其他实体借用后再借用导致的(这个本来应该在编译时就检测出来的,不知道为啥 55 | 运行的时候才报错)。看来解决办法是去掉 exclusive_access 56 | 57 | exclusive_access()不是 rust 的官方 core 库提供的,而是 rCore-Tutorial 的作者自己写的。代码就在 sync 58 | 文件夹里。注意到一行注释: 59 | 60 | ```rust 61 | /// Panic if the data has been borrowed. 62 | pub fn exclusive_access(&self) -> UPIntrRefMut<'_, T> { 63 | INTR_MASKING_INFO.get_mut().enter(); 64 | UPIntrRefMut(Some(self.inner.borrow_mut())) 65 | } 66 | ``` 67 | 68 | 再加上 readme 中的说明: 69 | 70 | > use `UPSafeCell` instead of `RefCell` or `spin::Mutex` in order to access static data structures 71 | > and adjust its API so that it cannot be borrowed twice at a time(mention 72 | > `& .exclusive_access().task[0]` in `run_first_task`) 73 | 74 | 还有 rCore-Tutorial-Book 上的: 75 | 76 | > 另一方面是提供了 UPIntrFreeCell 接口,代替了之前的 UPSafeCell 。在 Device OS 中把 77 | > UPSafeCell 改为 UPIntrFreeCell 。这是因为在第九章前,系统设置在 S-Mode 中屏蔽中断,所以在 78 | > S-Mode 中运行的内核代码不会被各种外设中断打断,这样在单处理器的前提下,采用 UPSafeCell 来实现对可 79 | > 写数据的独占访问支持是够用的。但在第九章中,系统配置改为在 S-Mode 中使能中断,所以内核代码在内核执 80 | > 行过程中会被中断打断,无法实现可靠的独占访问。本章引入了新的 UPIntrFreeCell 机制,使得在通过 81 | > UPIntrFreeCell 对可写数据进行独占访问前,先屏蔽中断;而对可写数据独占访问结束后,再使能中断。从而 82 | > 确保线程对可写数据的独占访问时,不会被中断打断或引入可能的线程切换,而避免了竞态条件的产生。 83 | 84 | 看来之前的推测没错。就是数据已经被借用了,再借用直接 panic 了。这也好办,不要获取数据,而是通过一个 85 | getter 获取数据的拷贝就行。 86 | 87 | 观察进程控制块结构体: 88 | 89 | ```rust 90 | pub struct ProcessControlBlock { 91 | // immutable 92 | pub pid: PidHandle, 93 | // mutable 94 | inner: UPIntrFreeCell, 95 | } 96 | ``` 97 | 98 | 最简单的方式是把 path 和 pid 并列,而不是放在 ProcessControlBlockInner 里,但是这样就破坏 99 | rCore-Tutorial 原有的设计了:外层放不变数据,内层(inner)放变化的数据(exec()之后 path 会变,所以 100 | path 算可变数据)。而要获取内层数据,必须经过 UPIntrFreeCell(这玩意大致就是“无中断容器”)的 101 | inner_exclusive_access. 这个设计对调试不太友好,不过还是有解决办法的,就是浅拷贝一份 102 | 103 | 不对,浅拷贝之前不还得 inner_exclusive_access......绕不开啊。 104 | 105 | 不过,好消息是,至少 uprobe 库是成功引入了,否则根本就不会报这个错。 106 | -------------------------------------------------------------------------------- /pre-record/2023-07-20.md: -------------------------------------------------------------------------------- 1 | ### 20230720 陈志扬 2 | 3 | #### 本周工作 4 | 5 | 1. 包含 ruprobe 库的内核能过编译了,os 能启动,但是刚加载完 initproc(还没运行)就会 panic.,原因是 6 | uprobe 模块初始化的时候需要获得 PCB 信息,因而需要 borrow PCB,但是 PCB 已经被其他代码给 borrow 7 | 了,不能再 borrow。(rCore-Tutorial-v3 故意用`UPIntrFreeCell` 包裹大部分的 PCB 数据,使得 PCB 不 8 | 能被同时 borrow 两次) 9 | 1. 开发日志 10 | ([7 月 16 日](https://github.com/chenzhiy2001/code-debug/blob/master/docs/2023-07-16.md)) 11 | ([7 月 19 日](https://github.com/chenzhiy2001/code-debug/blob/master/docs/2023-07-19.md)) 12 | 2. 此外上周那个问题问了彭淳毅,他也不知道咋办,问一些 rust 群,也没解决办法,考虑到它不是核心的功能 13 | (唯一功能是显示 TrapContext 的寄存器值),我暂时把这个功能去掉了(做法是传入 None) 14 | 15 | #### 下周工作 16 | 17 | 1. 改进 ruprobe; 18 | 2. 开始写文章; 19 | -------------------------------------------------------------------------------- /pre-record/2023-07-23.md: -------------------------------------------------------------------------------- 1 | uprobe 无法借用 PCB 的问题,只剩一个办法了,看下是谁借走了 PCB,调整一下时序,让大家好借好还,再借不 2 | 难。这个办法本身很容易想到,但是之前没这么干,主要是因为有以下难点: 3 | 4 | 1. GDB attach 不上,没法用调试器。 5 | 1. inner_exclusive_access() 是分散在代码里的,到处都是,光看代码很难厘清谁先谁后。只能通过添加输出信 6 | 息,在运行的时候输出,才能知道具体顺序。 7 | 1. UPIntrFreeCell 只是一个 Cell,Cell 本身不包含 inner_exclusive_access()函数调用者的信息,所以,如 8 | 果在 UPIntrFreeCell 里添加输出信息(这样只需要添加一行,很方便),是无法获悉函数调用者,或者 9 | UPIntrFreeCell 包裹的内容的信息的(不能知道 UPIntrFreeCell 里包裹的信息,是因为被包裹对象不一定实 10 | 现了 Debug Trait,因此根本就没办法在 UPIntrFreeCell 的代码里面 print,这样做连类型检查都过不去。 11 | 这和 py,js 之类的动态语言不同。)。 12 | 1. 除非引入 Backtrace 库,直接打印 backtrace。但是,这个 backtrace 库是 std 里的。而且,引入新的 13 | 库,说不准会引入新的麻烦。 14 | 1. 在调用 inner_exclusive_access()处加 print 是可行的,但是通过全局搜索发现 15 | ,inner_exclusive_access()在 rCore-Tutorial 里一共有七十个,数量比较多,得一个一个加 print,一个 16 | 一个分析。因为,通过之前的调试分析,发现在我出 bug 的那个瞬间,执行\_\_switch 的循环已经循环 2-3 17 | 次了,此时所有的模块都初始化完成了,都有可能是造成错误的原因。 18 | 1. 就算知道了是谁借走了 PCB 导致 uprobe 初始化模块不能再借用,也有可能没办法找到一种正确的借用顺序。 19 | 20 | 但是我们实在是没有其他办法了,只能硬上了。 21 | 22 | 加完 print 了,累死了,跑一跑试试。 23 | 24 | 不错,得到了一系列美观的输出: 25 | 26 | ```rust 27 | **************/ 28 | Getting PCB in src/task/id.rs TaskUserRes::new() 29 | Getting PCB in src/task/id.rs alloc_user_res() 30 | Getting PCB in src/task/id.rs trap_cx_ppn() 31 | Getting PCB in src/task/process.rs PCB::new() 32 | Getting PCB in src/task/task.rs get_user_token() 33 | Getting PCB in src/task/mod.rs suspend_current_and_run_next() 34 | Getting PCB in src/task/mod.rs check_signals_of_current() 35 | Getting PCB in src/task/task.rs get_user_token() 36 | Getting PCB in src/task/mod.rs check_signals_of_current() 37 | Getting PCB in src/task/task.rs get_user_token() 38 | Getting PCB in src/task/process.rs PCB::fork() 39 | Getting PCB AGAIN in src/task/process.rs PCB::fork() 40 | [ERROR] [kernel] Panicked at src/sync/up.rs:111 already borrowed: BorrowMutError 41 | ``` 42 | 43 | 看来这次运气不错,因为检查代码发现,“already borrowed”就是 fork 函数本身,也就是说我们在 fork()函数 44 | 里借了两次。不是那种两个函数借用的复杂情况。这个很好解决。在此处,我们借用 PCB 只是为了获取 PCB 中的 45 | path,不涉及页表修改,所以只需要在函数开头借用的时候就提前获取 path 即可。 46 | 47 | 代码修改好了,再跑一次。 48 | 49 | 成功了!!!! 50 | 51 | ```rust 52 | Getting PCB in src/task/mod.rs suspend_current_and_run_next() 53 | Getting PCB in src/task/process.rs PCB::exec() 54 | Getting PCB AGAIN in src/task/process.rs PCB::exec() 55 | Getting PCB AGAIN AGAIN in src/task/process.rs PCB::exec() 56 | Getting PCB in src/task/id.rs alloc_user_res() 57 | Getting PCB in src/task/id.rs trap_cx_ppn() 58 | [ INFO] uprobes_init 59 | get_exec_path 60 | Getting PCB in src/task/mod.rs get_exec_path() 61 | get_exec_path succeeded. path = user_shell 62 | [ INFO] uprobes: init sucess 63 | Getting PCB in src/task/mod.rs check_signals_of_current() 64 | Getting PCB in src/task/task.rs get_user_token() 65 | Getting PCB in src/task/task.rs get_user_token() 66 | Getting PCB in src/syscall/fs.rs sys_write() 67 | Rust user shell 68 | Getting PCB in src/task/mod.rs check_signals_of_current() 69 | Getting PCB in src/task/task.rs get_user_token() 70 | Getting PCB in src/task/task.rs get_user_token() 71 | ``` 72 | 73 | 当然,输出语句和等待输入的 sys_read 系统调用冲突了,我们无法在命令行中输入数据进一步验证功能是否可用 74 | 。(而且用户态的负责注册 uprobe 的程序还没写),我得先把这七十行 println 注释掉(早知道用 logger 了 75 | ) 76 | 77 | 好在这些输出语句的开头都是一样的`println!("Getting PCB`,因此可以用 VSCode 的全局搜索+全部替换。 78 | 79 | 再编译运行一次。看来 uprobe 启动成功了(不代表注册 uprobe 成功)。先跑一遍 usertests。 80 | 81 | ```rust 82 | [ INFO] uprobes_init 83 | get_exec_path 84 | get_exec_path succeeded. path = user_shell 85 | [ INFO] uprobes: init sucess 86 | Rust user shell 87 | >> 88 | ``` 89 | 90 | usertests 通过了,而且,输出信息显示,fork()的同时 uprobe 也在新进程里初始化了。这也是个好消息 91 | 92 | ```shell 93 | pidpid12: 1001 94 | pid24: 1010 95 | pid20: 1011 96 | 30: 1000 97 | Usertests: Test forktree in Process 3 exited with code 0 98 | Usertests: Running hello_world 99 | [ INFO] uprobes_init 100 | get_exec_path 101 | get_exec_path succeeded. path = hello_world 102 | [ INFO] uprobes: init sucess 103 | Hello world from user mode program! 104 | Usertests: Test hello_world in Process 3 exited with code 0 105 | Usertests: Running huge_write 106 | [ INFO] uprobes_init 107 | get_exec_path 108 | get_exec_path succeeded. path = huge_write 109 | ``` 110 | -------------------------------------------------------------------------------- /pre-record/2023-07-24.md: -------------------------------------------------------------------------------- 1 | 现在 uprobe 初始化成功了,下一步尝试注册一个 uprobe。 2 | 3 | 但是,在注册 uprobe 之前还有一个工作要做,就是把 name2addr 功能放到 os 外面,rCore-Tutorial 的 4 | kprobe,uprobe 代码直接处理地址(这也是 kprobe 原作者推荐的做法),但是逻辑上不太对。 5 | 6 | 修改了 parse_tracepoint()和 bpf_program_attach()的代码。考虑到这两个函数也被 kprobe 模块使用,我先测 7 | 试一下 kprobe 能不能正常用。 8 | -------------------------------------------------------------------------------- /pre-record/2023-07-30.md: -------------------------------------------------------------------------------- 1 | 昨天 uprobe 成功移植,并且给老师演示了。下一步是: 2 | 3 | 1. 写文档,ppt,整理开发日志,写论文 4 | 2. 整理一个部署指南,使得其他同学能用上,其他同学用上之后再完善文档 5 | 3. 尝试利用 iPerf 做一个应用例子 6 | 7 | iPerf 的源代码我昨天下载下来了,今天看到里面有个安装指南(叫 INSTALL),可以看看。安装指南说,首次编 8 | 译后会生成一个可以修改的配置文件。那么我们只要先在 Ubuntu 里编译一次,然后修改配置文件中的编译器等信 9 | 息,就可以交叉编译到基于 RISC-V 的 rCore-Tutorial-v3 了。 10 | 11 | iPerf 是基于 C 的。在我们版本的 rCore-Tutorial 里的 ucore 文件夹下,已经有一些现成的关于 12 | rCore-Tutorial-v3 的用户态程序的 C 编译选项,可以参考。 13 | 14 | 其实`./configure --help`已经暴露出来一些配置参数,但是和 rCore-Tutorial-v3/ucore/CMakeList.txt 的比 15 | 起来还是不够。所以还是得先在 ubuntu 上编译一遍。 16 | 17 | 编译完成了,发现 iperf 分 client 和 server 两个模式,那 ubuntu 上的这个安装到时候也能发挥作用。 18 | 19 | 我用的自动配置`./configure`,结果安装失败了,这个软件压根不能跑:iperf3: error while loading shared 20 | libraries: libiperf.so.0: cannot open shared object file: No such file or directory 21 | 22 | 上网搜了一下,运行`ldconfig`之后,就能正常打开 iperf 了。先试着在 ubuntu 上用一下。结果卡住了。可能 23 | 因为我开了梯子。 24 | 25 | 发现自己电脑上居然没有 ifconfig,看自己 ip 不太方便,于是安装 net-tools. 26 | 27 | 获得了自己的 ip,在 ubuntu 上跑了一次 iPerf: 28 | 29 | ```shell 30 | oslab@ubuntu:~$ iperf3 -s 31 | ----------------------------------------------------------- 32 | Server listening on 5201 33 | ----------------------------------------------------------- 34 | Accepted connection from 192.168.80.131, port 53094 35 | [ 5] local 192.168.80.131 port 5201 connected to 192.168.80.131 port 53108 36 | [ ID] Interval Transfer Bandwidth 37 | [ 5] 0.00-1.00 sec 3.07 GBytes 26.4 Gbits/sec 38 | [ 5] 1.00-2.00 sec 3.99 GBytes 34.3 Gbits/sec 39 | [ 5] 2.00-3.00 sec 4.32 GBytes 37.1 Gbits/sec 40 | [ 5] 3.00-4.00 sec 4.10 GBytes 35.2 Gbits/sec 41 | [ 5] 4.00-5.00 sec 4.53 GBytes 38.9 Gbits/sec 42 | [ 5] 5.00-6.00 sec 4.32 GBytes 37.1 Gbits/sec 43 | [ 5] 6.00-7.00 sec 4.78 GBytes 41.0 Gbits/sec 44 | [ 5] 7.00-8.00 sec 4.00 GBytes 34.3 Gbits/sec 45 | [ 5] 8.00-9.00 sec 4.60 GBytes 39.5 Gbits/sec 46 | [ 5] 9.00-10.00 sec 4.19 GBytes 36.0 Gbits/sec 47 | [ 5] 10.00-10.04 sec 110 MBytes 20.7 Gbits/sec 48 | - - - - - - - - - - - - - - - - - - - - - - - - - 49 | [ ID] Interval Transfer Bandwidth 50 | [ 5] 0.00-10.04 sec 0.00 Bytes 0.00 bits/sec sender 51 | [ 5] 0.00-10.04 sec 42.0 GBytes 35.9 Gbits/sec receiver 52 | ----------------------------------------------------------- 53 | Server listening on 5201 54 | ----------------------------------------------------------- 55 | ``` 56 | 57 | 了解了它的使用方式后,下一步是交叉编译到 rCore。不过,我看了一下 iPerf 的配置文件,没有清晰的思路。 58 | 所以去 iPerf 的 Github 上问了问: 59 | 60 | 在等待回答的期间,我应该写文档和界面。我查了下,VSCode 有输入调试控制台的 API,所以事情会比较好办 61 | : 62 | 63 | 先写文档吧。在写文档之前,先把东西 commit 上去。已经 commit, push 到 github 了,发现现在已经有五个代 64 | 码仓库了。打算先写 uprobe 移植指南,因为这部分内容最少。 65 | -------------------------------------------------------------------------------- /pre-record/2023-07-31.md: -------------------------------------------------------------------------------- 1 | uprobe 移植指南已经写了一半了。 2 | 3 | 尝试跑 iPerf,昨天在 rCore-Tutorial-v3 的交流群里问了一下(iperf github 也问了,没人理我)有大佬说 4 | iPerf 是今年内核赛的测例。今天找着了,发现测例是包含源代码的,且 Makefile 里已经写清楚用什么编译参数 5 | ,测试脚本里也写清楚怎么测试了。那我就直接用内核赛的编译,测试参数了,不再自己作调整了。这样也更具说 6 | 服力。 7 | 8 | Makefile: 9 | 10 | ```Makefile 11 | iperf: .PHONY 12 | cd iperf && ./configure --host=riscv64-linux-musl CC=$(MUSL_GCC) --enable-static-bin --without-sctp && make 13 | cp iperf/src/iperf3 sdcard/ 14 | cp scripts/iperf/iperf_testcode.sh sdcard/ 15 | ``` 16 | 17 | 测试脚本: 18 | 19 | ```sh 20 | host="127.0.0.1" 21 | port="5001" 22 | iperf="./iperf3" 23 | 24 | run_iperf() { 25 | name=$1 26 | args=$2 27 | echo "====== iperf $name begin ======" 28 | 29 | $iperf -c $host -p $port -t 2 -i 0 $args 30 | if [ $? == 0 ]; then 31 | ans="success" 32 | else 33 | ans="fail" 34 | fi 35 | 36 | echo "====== iperf $name end: $ans ======" 37 | echo "" 38 | } 39 | 40 | 41 | #start server 42 | $iperf -s -p $port -D 43 | 44 | #basic test 45 | run_iperf "BASIC_UDP" "-u -b 1000G" 46 | run_iperf "BASIC_TCP" "" 47 | 48 | #parallel test 49 | run_iperf "PARALLEL_UDP" "-u -P 5 -b 1000G" 50 | run_iperf "PARALLEL_TCP" "-P 5" 51 | 52 | #reverse test (server sends, client recieves) 53 | run_iperf "REVERSE_UDP" "-u -R -b 1000G" 54 | run_iperf "REVERSE_TCP" "-R" 55 | 56 | ``` 57 | 58 | 我们的 shell 不支持跑 shell 脚本,因此我们得手动输入这些命令,好在比较简短,并不太费事。 59 | 60 | 试着编译一下,发现居然`./configure`不了,原来我们的编译器是 riscv-linux-musl-gcc 不是 Makefile 里的 61 | riscv-linux-gcc. 62 | 63 | 修改之后,可以`./configure`了,但是还是编译不了: 64 | 65 | ```shell 66 | /home/oslab/riscv64-linux-musl-cross/bin/../lib/gcc/riscv64-linux-musl/11.2.1/../../../../riscv64-linux-musl/bin/ld: cannot find -lssl 67 | /home/oslab/riscv64-linux-musl-cross/bin/../lib/gcc/riscv64-linux-musl/11.2.1/../../../../riscv64-linux-musl/bin/ld: cannot find -lcrypto 68 | ``` 69 | 70 | 找不到这些 Lib 文件。先看看链接器是否能找到这些库: 71 | 72 | ```shell 73 | riscv64-linux-musl-ld -lssl --verbose 74 | riscv64-linux-musl-ld -lcrypto --verbose 75 | ``` 76 | 77 | 结果显示都没找到。看来要添加这些库。而且,似乎不能直接通过包管理器安装。 78 | -------------------------------------------------------------------------------- /pre-record/2023-08-01.md: -------------------------------------------------------------------------------- 1 | 接着昨天的工作继续,我越想越离谱,要是这个 musl 真的没有 ssl,crypto 这类的库,那岂不是没法写 https 2 | 应用了,这怎么可能?应该是链接器没能找到这些库文件。做了以下尝试: 3 | 4 | 1. 尝试在自己机子上的 musl 里搜索,看看是否有相关的库。没找着 5 | 1. 尝试在 musl 源代码里搜索,看是否有相关源代码文件 6 | 1. 之前用的是 musl.cc 上下载的,这回看看能不能自己编译一个。去 musl 网站上看了一下, 7 | 有[musl-cross-make](https://github.com/richfelker/musl-cross-make).并且也提供了配置文件,可能我们 8 | 需要调整配置文件`config.mak`. 9 | 10 | iPerf 的事情先缓一缓,先做重要的事情: 11 | 12 | 1. 写完 uprobe 库的文档 13 | 2. 写调试器的配置文档 14 | 3. 弄 iPerf 测试并记录过程,这个过程就是 OS 比赛提交的文档的一部分。 15 | 4. 弄文档的其余部分. 16 | 5. 写论文 17 | 18 | 应该这个顺序. 19 | -------------------------------------------------------------------------------- /pre-record/2023-08-04.md: -------------------------------------------------------------------------------- 1 | 和老师商量了一下,iPerf 这个事先不做了,一是没时间,二是有更重要的事情。现在先去写文档,等文档写到一 2 | 定程度,我会再在开发日志里记录怎么利用 uprobe 和基于 rCore-Tutorial 的 simplehttp 程序或者另外的 3 | rust 网络基准测试程序找出操作系统的问题。写文档想要写得好,关键是要把背后的理论说明白。如果不知道什 4 | 么理论,可以从代码反找到指导书,再去查相关的教材,论文,或许有线索。 5 | -------------------------------------------------------------------------------- /pre-record/2023-08-06.md: -------------------------------------------------------------------------------- 1 | ## 概述 2 | 3 | 接下来我们用我们的调试器调试 rCore-Tutorial 自带的 http 服务器,从中可以看出 GDB+eBPF 带来的方便。 4 | 5 | ## Bug 描述 6 | 7 | `tcp-simplehttp` 是 rCore-Tutorial 自带的一个简单的 HTTP 服务器。服务器启动之后,在浏览器访问对应的 8 | URL 即可获得服务器返回的静态页面。但是,如果我们在浏览器里打开多个标签页,每打开一个标签页,就在这个 9 | 标签页里访问服务器的 URL,就会发现一个奇怪的现象:一部分标签页成功显示出了网页,另一部分则一直在加载 10 | 中,始终无法显示网页。而且,加载成功的标签页和加载失败的标签页是**交替出现**的。 11 | 12 | ![simplehttp服务器无法返回所有网页请求](./imgs/browser_simplehttp_multiple_tab_bug.png) 13 | 14 | 作为对比,我们用同样的方式重复打开全国大学生计算机系统能力大赛的官网,结果是所有标签页都正常地打开了 15 | : 16 | 17 | ![操作系统比赛官网可以返回所有网页请求](./imgs/browser_os_multiple_tab.png) 18 | 19 | 接下来,我们尝试在操作系统调试器的帮助下找到出错的原因并修复这个错误。 20 | 21 | ## 代码简述 22 | 23 | 在开始使用调试器之前,我们阅读了这个服务器的源代码,从而大致了解了它的工作流程:当服务器启动,进入到 24 | main 函数后,main 函数就会调用`listen()`库函数,在 80 端口开始监听。如果接收到客户端的连接,就调用 25 | handle_tcp_client 函数处理来自客户端的请求。handle_tcp_client 函数会先读取请求并检查是否为有效的 26 | HTTP GET 请求,如果是的话,就从请求中提取出 URL ,并返回 URL 对应的 HTML 网页。此外,如果用户访问的 27 | 是 `/close` 页面,服务器会在返回一个表示服务器关闭的网页后终止连接,并关闭服务器自身。 28 | 29 | ## Debug 过程 30 | 31 | 首先,我怀疑服务器是否接收到了所有的 HTTP 请求。因此我们在服务器的 accept() 函数设置一个 eBPF 断点。 32 | 这个 eBPF 断点会返回当前的所有寄存器值。从而获得`accept`函数的返回值和参数。 33 | 34 | 设置断点后,我们打开服务器,重复访问同一个网址。发现了两个异常现象: 35 | 36 | 1. 在浏览器尚未访问网址时,accept()函数就被调用了一次。 37 | 2. 浏览器打开六个标签页(每一个标签页都向服务器请求同一个网址),只有四个标签页正确显示出了内容 38 | 。accept()函数在这段时间内只触发了四次断点,正常状况下应该是六个断点才对。 39 | 40 | 这个初步的尝试显示,问题可能出在内核没有成功接收到所有的 HTTP 请求,或者内核接收到了所有的请求,却没 41 | 有全部传送给应用程序。 42 | 43 | 为了确认具体的出错位置,我们从内核网络栈的代码到系统调用,再到用户态程序上设置了多个内核和应用程序的 44 | eBPF 断点,看看是哪个环节出了问题。 45 | 46 | 内核函数如下: | 函数名 | 地址 | |-----------------------|------------------| | receive | 47 | 000000008021c0ca | | net_interrupt_handler | 0000000080212c24 | | sys_accept | 0000000080216e5a | | 48 | syscall | 000000008021315e | 49 | 50 | syscall 不行,用 GDB 51 | 52 | 用户函数如下: | 函数名 | 地址 | |--------|------------------| | listen | 0x000109fe | | accept | 53 | 0x00010a1c | 54 | 55 | 设置完断点后, 56 | 57 | In firefox, every tab is a thread while in Chrome every tab is a process. Is this bug appear in 58 | Chrome? 59 | 60 | 我们大概定位到了出错位置:。再利用 GDB 的单步调试 61 | 62 | 这样,结合 eBPF 和 GDB 两种调试手段,这个 bug 被快速定位并修复了。除了这一处代码,在整个 Debug 的过 63 | 程中,我们不需要出于调试目的而改动任何其他的源代码。 64 | 65 | ## 另一个 bug 66 | 67 | ```rust 68 | [ INFO] Device features (empty) 69 | [DEBUG] Got MAC=[0, 0, 0, 0, 0, 0], status=(empty) 70 | [ERROR] [kernel] Panicked at src/drivers/net/mod.rs:41 can't create net device by virtio: InvalidParam 71 | ---START BACKTRACE--- 72 | #0:ra=0x80219f12 73 | #1:ra=0x80246fb6 74 | ``` 75 | 76 | 这个是 launch.json 中 qemu 启动参数不对,没有注册网络端口导致的。 77 | -------------------------------------------------------------------------------- /pre-record/2023-08-10.md: -------------------------------------------------------------------------------- 1 | 今天把界面给补上。首先第一个问题就是获取 Qemu 的输出,这样才能知道第二个串口的具体地址。想了很多的办 2 | 法,最后发现`tee`命令最好使。修改了一下 Qemu 启动的命令。 3 | -------------------------------------------------------------------------------- /pre-record/2023-08-14.md: -------------------------------------------------------------------------------- 1 | 这几天做界面,写文档和 PPT。 2 | 3 | 之前报错的原因找到了,我自己代码写错了。出错代码如下: 4 | 5 | ```rust 6 | /// Test whether this area is (page) overlap with area [`start_addr`, `end_addr`) 7 | pub fn is_overlap_with(&self, start_addr: VirtAddr, end_addr: VirtAddr) -> bool { 8 | // original from rCore-ebpf: 9 | // let p0 = Page::of_addr(self.start_addr); 10 | // let p1 = Page::of_addr(self.end_addr - 1) + 1; 11 | // let p2 = Page::of_addr(start_addr); 12 | // let p3 = Page::of_addr(end_addr - 1) + 1; 13 | // if OS crashes, here should be the first place to check with. 14 | let p0 = self.vpn_range.get_start(); 15 | let p1 = VirtPageNum(self.vpn_range.get_end().0+PAGE_SIZE); //czy is this mathematically correct? 16 | let p2 = start_addr.floor();//VirtPageNum::from(start_addr); 17 | let p3 = start_addr.ceil();//VirtPageNum::from(end_addr.0+PAGE_SIZE);//Page::of_addr(end_addr - 1) + 1; 18 | !(p1 <= p2 || p0 >= p3) 19 | } 20 | ``` 21 | 22 | 我看到 end_addr 在编辑器里的颜色的偏灰的,表示这个变量根本没被使用。这段代码的用处是检验[p2,p3)和 23 | [p0,p1)是不是重合的。那很明显 p3 应该是`end_addr.ceil()`才对,当时我可能把这里误解成找出某个页的 24 | ceil 和 floor 了,所以写错了。这个错误花了一周才发现,看来好的调试工具确实很有必要。 25 | 26 | 还有个错误,居然往页号上加 PAGE_SIZE....难怪内存不够用。修改后的代码如下: 27 | 28 | ```rust 29 | /// Test whether this area is (page) overlap with area [`start_addr`, `end_addr`) 30 | pub fn is_overlap_with(&self, start_addr: VirtAddr, end_addr: VirtAddr) -> bool { 31 | // original from rCore-ebpf: 32 | // let p0 = Page::of_addr(self.start_addr); 33 | // let p1 = Page::of_addr(self.end_addr - 1) + 1; 34 | // let p2 = Page::of_addr(start_addr); 35 | // let p3 = Page::of_addr(end_addr - 1) + 1; 36 | // if OS crashes, here should be the first place to check with. 37 | let p0 = self.vpn_range.get_start().0; 38 | let p1 = VirtPageNum::from(VirtAddr::from(self.vpn_range.get_end()).0-1).0+1; 39 | let p2 = start_addr.floor().0;//VirtPageNum::from(start_addr); 40 | let p3 = end_addr.ceil().0;//VirtPageNum::from(end_addr.0+PAGE_SIZE);//Page::of_addr(end_addr - 1) + 1; 41 | !(p1 <= p2 || p0 >= p3) 42 | } 43 | 44 | ``` 45 | 46 | 这改得不对,还是不行。这段代码可读性最差的地方就是最后一行`!(p1 <= p2 || p0 >= p3)`。它的意思是这样 47 | 的: 48 | 49 | 在正常情况下,如果两个区间[p0,p1),[p2,p3)不重叠,只有两种情况: 50 | 51 | 1. `p0-p1, p2-p3` 52 | 2. `p2-p3, p0-p1` 53 | 54 | 其中,p0 < p1 和 p2 < p3 这两个条件肯定是满足的,因此只需要检查 p1 与 p2 ,p3 与 p0 的关系。 55 | 56 | 在第一种情况下,p1<=p2 ;在第二种情况下,p3<=p0。如果这两个情况都不出现,那么就是重叠了。 57 | 58 | 但是,这种推理方式的前提是,给定的区间都是左闭右开的,而 rCore-Tutorial-v3 的内存区间相关的数据结构 59 | 都是闭区间(文档里没明说,我根据代码和自己的实验猜测的)。因此,与其将闭区间转换成左闭右开,不如直接 60 | 改写成闭区间的写法,就不会写错了,而且代码简洁不少: 61 | 62 | ```rust 63 | 64 | pub fn is_overlap_with(&self, start_addr: VirtAddr, end_addr: VirtAddr) -> bool { 65 | let p0 = self.vpn_range.get_start(); 66 | let p1 = self.vpn_range.get_end(); 67 | let p2 = start_addr.floor(); 68 | let p3 = end_addr.ceil(); 69 | !(p1 < p2 || p0 > p3) 70 | } 71 | 72 | 73 | ``` 74 | 75 | 这样修改之后,kprobe 和多个进程的 uprobe 就正常运行了。至此,所有的代码我们都修改完毕了。 76 | -------------------------------------------------------------------------------- /pre-record/2023-oscomp-share-13.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/2023-oscomp-share-13.pdf -------------------------------------------------------------------------------- /pre-record/2023S.md: -------------------------------------------------------------------------------- 1 | ## 安装 2 | 3 | 1. 运行一遍 rCore-Tutorial-Code-2023S ch9 4 | 2. 根据这 5 | 个[diff 文件](https://github.com/chenzhiy2001/code-debug/blob/master/docs/diff-rCore-Tutorial-Code-2023S-kernel.diff)修 6 | 改代码,然后进入 user 目录,根据这 7 | 个[diff 文件](https://github.com/chenzhiy2001/code-debug/blob/master/docs/diff-rCore-Tutorial-Code-2023S-user.diff)修 8 | 改代码,然后再跑一遍,确保能正常运行 9 | 3. 下载 SiFive 提供 10 | 的[risc-v 工具链](https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-8.3.0-2020.04.1-x86_64-linux-ubuntu14.tar.gz)。 11 | 下载后将该文件复制到 home 目录下并解压. 将其中的 bin/文件夹加入环境变量. 12 | 4. `cd ..../your_dir/ && git clone https://github.com/chenzhiy2001/code-debug.git && cd code-debug/ && npm install` 13 | (确保您已经安装了较新版本的 npm) 14 | 5. 打开 vscode,打开 your_dir/code-debug/文件夹. 15 | 6. 切换到`br-chenzhiy2001-hardcode-for-2023S`分支,然后将 code-debug/src/frontend/extension.ts 中的 16 | 16 行改成您要 debug 的 rCore 的位置,比如 os.homedir() + "/rCore-Tutorial-Code-2023S", 17 | 再`npm install`. 18 | 1. 如果您不想这么做,而是想留在`master`分支,那么请参照[这里](#硬编码数据修改). 19 | 7. 保存,然后按 f5,会弹出一个新的 vscode 窗口. 在新窗口中打开 rCore-Tutorial-Code-2023S/ 20 | 8. 在 .vscode 文件夹中添加 launch.json 文件,并输入以下内容(注意有三 21 | 处`${userHome}/your/path/to/rCore-Tutorial-Code-2023S`要修改成你的 rCore 的位置),保存后再编译运 22 | 行一遍 rCore,然后按 F5 就可以启动 gdb 并调试。 23 | ``` 24 | //launch.json 25 | { 26 | "version": "0.2.0", 27 | "configurations": [ 28 | { 29 | "type": "gdb", 30 | "request": "launch", 31 | "name": "Attach to Qemu", 32 | "executable": "${userHome}/your/path/to/rCore-Tutorial-Code-2023S/os/target/riscv64gc-unknown-none-elf/release/os", //修改${userHome}/your/path/to/ 33 | "target": ":1234", 34 | "remote": true, 35 | "cwd": "${workspaceRoot}", 36 | "valuesFormatting": "parseText", 37 | "gdbpath": "riscv64-unknown-elf-gdb", //如果GDB并没有正常启动,可以尝试改成绝对路径(如“/home/username/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin”) 38 | "showDevDebugOutput":true, 39 | "internalConsoleOptions": "openOnSessionStart", 40 | "printCalls": true, 41 | "stopAtConnect": true, 42 | "qemuPath": "qemu-system-riscv64", 43 | "qemuArgs": [ 44 | "-M", 45 | "128m", 46 | "-machine", 47 | "virt", 48 | "-bios", 49 | "${userHome}/your/path/to/rCore-Tutorial-Code-2023S/bootloader/rustsbi-qemu.bin",//修改${userHome}/your/path/to/ 50 | "-display", 51 | "none", 52 | "-device", 53 | "loader,file=${userHome}/your/path/to/rCore-Tutorial-Code-2023S/os/target/riscv64gc-unknown-none-elf/release/os.bin,addr=0x80200000",//修改${userHome}/your/path/to/ 54 | "-drive", 55 | "file=${userHome}/your/path/to/rCore-Tutorial-Code-2023S/user/target/riscv64gc-unknown-none-elf/release/fs.img,if=none,format=raw,id=x0",//修改${userHome}/your/path/to/ 56 | "-device", 57 | "virtio-blk-device,drive=x0", 58 | "-device", 59 | "virtio-gpu-device", 60 | "-device", 61 | "virtio-keyboard-device", 62 | "-device", 63 | "virtio-mouse-device", 64 | "-serial", 65 | "stdio", 66 | "-s", 67 | "-S" 68 | ] 69 | }, 70 | ] 71 | } 72 | ``` 73 | 74 | ## 使用 75 | 76 | 1. 等一会,喝杯水,直到 DEBUG CONSOLE 不再刷新内容 77 | 1. 按 TERMINAL 可以切换到终端输出 78 | 1. 按下清除所有断点(`removeAllCliBreakpoints`)按钮,在右上角,🗑 垃圾桶图标 79 | 1. 按下设置内核入口(`setKernelInBreakpoints`)按钮 80 | 1. 按下出口断点(`setKernelOutBreakpoints`)按钮 81 | 1. 设置你想要的内核代码和用户程序代码的断点(推荐在 main.rs 的`trap::init()`设置一个,在 82 | ch9b_initproc.rs 的`println!("aaaa")`语句设置一个,如果不行的话设置在`fn main() -> i32 {`处) 83 | 1. 按 continue 按钮(`|▷`)开始运行 rCore-Tutorial.接下来不停按`|▷`就行了. 84 | 1. 当运行到位于内核出口的断点时,插件会自动切换到用户态的断点 85 | 1. 在用户态程序中如果想观察内核内的执行流,可以点击`gotokernel`按钮,然后点击继续按钮,程序会停在 86 | 内核的入口断点,这时,可以先把内核出口断点设置好(点击`setKernelOutBreakpoints`按钮),接下来 87 | ,可以在内核态设置断点,点击继续,运行到内核的出口断点之后,会回到用户态。 88 | 89 | ## 硬编码数据修改 90 | 91 | 改成一个 vscode 设置选项可能更方便,欢迎 pr: 92 | 93 | 1. code-debug/src/mibase.ts 94 | 1. 1255 行,65 改成 79 95 | 2. 1264 行和 343 行,135 改成 148 96 | 3. 1281 行,30 改成 43 97 | 2. code-debug/src/frontend/extension.ts 98 | 1. 15 行 initproc 改成 ch9b_initproc 99 | 2. 16 行改成您要 debug 的 rCore 的位置,比如 os.homedir() + "/rCore-Tutorial-Code-2023S" 100 | -------------------------------------------------------------------------------- /pre-record/2023操作系统设计赛参赛经验分享-陈志扬.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/2023操作系统设计赛参赛经验分享-陈志扬.pptx -------------------------------------------------------------------------------- /pre-record/2024-01-08.md: -------------------------------------------------------------------------------- 1 | 首先根据 arceos 主页安装`cargo-binutils` `libclang-dev` `cross-musl-based` 等工具。然后我们安装 2 | riscv64,x86_64,aarch64 虚拟机: 3 | 4 | ```shell 5 | cd qemu-7.0.0/ 6 | ./configure --target-list=aarch64-softmmu,riscv64-softmmu,x86_64-softmmu,aarch64-linux-user,aarch64_be-linux-user,riscv64-linux-user,x86_64-linux-user 7 | make -j$(nproc) 8 | ``` 9 | 10 | 在你的终端配置文件中添加: 11 | 12 | ``` 13 | export PATH=$PATH:/home/oslab/qemu-7.0.0/build 14 | ``` 15 | 16 | 然后重启终端。我们之前已经运行过 riscv 的了(),因此 17 | 尝试运行 x86_64: 18 | 19 | ``` 20 | make A=./apps/helloworld/ ARCH=x86_64 LOG=info run 21 | ``` 22 | 23 | 遇到错误: 24 | 25 | ``` 26 | Running on qemu... 27 | qemu-system-x86_64 -m 128M -smp 1 -machine q35 -kernel ./apps/helloworld//helloworld_x86_64-qemu-q35.elf -nographic -cpu host -accel kvm 28 | Could not access KVM kernel module: No such file or directory 29 | qemu-system-x86_64: -accel kvm: failed to initialize kvm: No such file or directory 30 | make: *** [Makefile:162: justrun] Error 1 31 | 32 | ``` 33 | 34 | 原因是我的 Linux 是跑在 VMWare 虚拟机里的,不支持 KVM. 因此去掉`-cpu host -accel kvm`参数: 35 | 36 | ``` 37 | qemu-system-x86_64 -m 128M -smp 1 -machine q35 -kernel ./apps/helloworld/helloworld_x86_64-qemu-q35.elf -nographic 38 | ``` 39 | 40 | 运行成功. 接着我们把这个 qemu 启动参数搬到 `launch.json` 里. 由于这里 qemu 直接启动 elf 而不是 bin 41 | 文件,`launch.json`也做对应的调整: 42 | 43 | ```json 44 | //launch.json 45 | { 46 | "version": "0.2.0", 47 | "configurations": [ 48 | { 49 | "type": "gdb", 50 | "request": "launch", 51 | "name": "Attach to Qemu", 52 | "executable": "${userHome}/arceos/apps/helloworld/helloworld_x86_64-qemu-q35.elf", 53 | "target": ":1234", 54 | "remote": true, 55 | "cwd": "${workspaceRoot}", 56 | "valuesFormatting": "parseText", 57 | "gdbpath": "gdb-multiarch", 58 | "showDevDebugOutput": true, 59 | "internalConsoleOptions": "openOnSessionStart", 60 | "printCalls": true, 61 | "stopAtConnect": true, 62 | "qemuPath": "qemu-system-x86_64", 63 | "qemuArgs": [ 64 | "-M", 65 | "128m", 66 | "-smp", 67 | "1", 68 | "-machine", 69 | "q35", 70 | "-kernel", 71 | "apps/helloworld/helloworld_x86_64-qemu-q35.bin", 72 | "-nographic", 73 | "-s", 74 | "-S" 75 | ], 76 | 77 | "KERNEL_IN_BREAKPOINTS_LINE": 65, // src/trap/mod.rs中内核入口行号。可能要修改 78 | "KERNEL_OUT_BREAKPOINTS_LINE": 124, // src/trap/mod.rs中内核出口行号。可能要修改 79 | "GO_TO_KERNEL_LINE": 30 // src/trap/mod.rs中,用于从用户态返回内核的断点行号。在rCore-Tutorial-v3中,这是set_user_trap_entry函数中的stvec::write(TRAMPOLINE as usize, TrapMode::Direct);语句。 80 | } 81 | ] 82 | } 83 | ``` 84 | 85 | arceos-httpserver 也跑通了。只需要注意 qemu 开放的 tcp 端口不要和 gdb 占用的端口有重叠即可。 86 | -------------------------------------------------------------------------------- /pre-record/2024-01-14.md: -------------------------------------------------------------------------------- 1 | ## 用 code-debug 调试 x86 Starry 2 | 3 | 注:此文档过时了,请移步 readme.md 查看相关信息 4 | 5 | 首先,我们将 Makefile 中的 `MODE ?= release` 改为 `MODE ?= debug` 6 | 7 | 其次,将主目录中的 Cargo.toml 里的`lto = true`注释掉 8 | 9 | 接着,将`modules/axdriver/build.rs`里的`.align 16`改为`.align 4096` 10 | 11 | 最后,运行 Starry 并输出到一个文本文件中: 12 | 13 | ``` 14 | ./build_img.sh sdcard 15 | make A=apps/oscomp LOG=debug QEMU_LOG=y ARCH=x86_64 run > output.txt 16 | ``` 17 | 18 | 打开`output.txt`并将 Qemu 的启动参数修改为`launch.json`: 19 | 20 | ```json 21 | //launch.json 22 | { 23 | "version": "0.2.0", 24 | "configurations": [ 25 | { 26 | "type": "gdb", 27 | "request": "launch", 28 | "name": "Attach to Qemu", 29 | "executable": "${userHome}/Starry-x86/Starry/apps/oscomp/oscomp_x86_64-qemu-q35.elf", 30 | "target": ":1234", //不能和Qemu开放的tcp端口重叠 31 | "remote": true, 32 | "cwd": "${workspaceRoot}", 33 | "valuesFormatting": "parseText", 34 | "gdbpath": "gdb-multiarch", 35 | "showDevDebugOutput": true, 36 | "internalConsoleOptions": "openOnSessionStart", 37 | "printCalls": true, 38 | "stopAtConnect": true, 39 | "qemuPath": "qemu-system-x86_64", 40 | "qemuArgs": [ 41 | "-m", 42 | "2G", 43 | "-smp", 44 | "1", 45 | "-machine", 46 | "q35", 47 | "-kernel", 48 | "apps/oscomp/oscomp_x86_64-qemu-q35.elf", 49 | "-device", 50 | "virtio-blk-pci,drive=disk0", 51 | "-drive", 52 | "id=disk0,if=none,format=raw,file=disk.img", 53 | "-device", 54 | "virtio-net-pci,netdev=net0", 55 | "-netdev", 56 | "user,id=net0,hostfwd=tcp::1235-:5555,hostfwd=udp::5555-:5555", 57 | "-nographic", 58 | "-s", 59 | "-S" 60 | ], 61 | "userSpaceDebuggeeFolder": "${userHome}/Starry-x86/Starry/testcases/sdcard/bin/", 62 | "KERNEL_IN_BREAKPOINTS_LINE": 12, // src/trap/mod.rs中内核入口行号。可能要修改 63 | "KERNEL_OUT_BREAKPOINTS_LINE": 770, // src/trap/mod.rs中内核出口行号。可能要修改 64 | "GO_TO_KERNEL_LINE": 30, // src/trap/mod.rs中,用于从用户态返回内核的断点行号。在rCore-Tutorial-v3中,这是set_user_trap_entry函数中的stvec::write(TRAMPOLINE as usize, TrapMode::Direct);语句。 65 | "KERNEL_IN_BREAKPOINTS_FILENAME": "/home/oslab/Starry-x86/Starry/modules/axhal/src/arch/x86_64/trap.rs", 66 | "KERNEL_OUT_BREAKPOINTS_FILENAME": "/home/oslab/Starry-x86/Starry/modules/axtask/src/task.rs", 67 | "GO_TO_KERNEL_FILENAME": "" 68 | } 69 | ] 70 | } 71 | ``` 72 | 73 | 一定要 debug 模式。release 模式没有文件名 74 | 75 | riscv 版本:离谱:debug 一定要用 lto Failed to get Stack Trace: PC not saved (from stack-info-depth 76 | --thread 1) 77 | 78 | 1. gdb 冲突,hex 依赖 79 | 2. 提醒用户装 rustfilt 和 nm(用于 ebpf panel) 还有 xdotools 80 | 3. 修改 \_\_metadata 81 | 82 | 两个 bug: 83 | 84 | - vscode 要切换页面才会显示断点变色(问题排查不出来,gui 问题,不非常影响使用,暂缓) 85 | - 修改 \_\_metadata 86 | - 找到了 Starry 没法调试用户态的原因,接下来要据此修改源码和文档:边界断点之前的逻辑(用户打**位置靠 87 | 前的**用户态断点并被插件暂存-用户 continue-边界断点触发-插件进行断点组切换-用户**continue**-用户态 88 | 断点触发)有局限性(在 rCore-Tutorial-v3 的特权级切换的时候有用跳板页所以这招可以用,但不是所有 OS 89 | 都有用跳板页。参考),找杨金博演示了 90 | 以下熟练的工程师使用 GDB 跳到用户态的方式,应该改成这种:(用户 continue-边界断点触发-插件不停地单 91 | 步,检测是否到达用户态-如果到达用户态,进行断点组切换) 92 | - 边界断点触发-插件进行断点组切换 改为 边界断点触发-插件不停地单步,检测是否到达用户态-如果到达用 93 | 户态,进行断点组切换 94 | - (这个要仔细问一下并记录下来)由于 sv39 页表的设计,高 xx 位要和从右往左数第九位一致,所以尽管 95 | risc-v 的内存布局可以自己乱搞,但是惯例上来说,f 开头的都是内核。 96 | 97 | - 结构体展开 98 | -------------------------------------------------------------------------------- /pre-record/Slides-August.md: -------------------------------------------------------------------------------- 1 | --- 2 | marp: true 3 | theme: default 4 | paginate: true 5 | _paginate: false 6 | header: "" 7 | footer: "" 8 | backgroundColor: white 9 | --- 10 | 11 | # proj158 12 | 13 | 支持 Rust 语言的源代码级内核调试工具 14 | 15 | **指导老师**:吴竞邦 (北京工商大学) 16 | 17 | **团队成员**:陈志扬 余叶 黄宗益 (北京工商大学) 18 | 19 | --- 20 | 21 | ## 起因 22 | 23 | - rCore-Tutorial 实验 24 | - 环境配置繁琐 25 | - GDB TUI 不方便 26 | 27 | --- 28 | 29 | ## 在线调试系统 30 | 31 | - 浏览器打开即用 32 | - 类似 github classroom 33 | - 提供在线 VSCode 34 | - 调试者与被调试内核分离 35 | - VSCode 插件支持操作系统相关的调试功能 36 | - 插件也可以在本地版本 VSCode 上使用 37 | 38 | --- 39 | 40 | ## 功能 41 | 42 | - 寄存器 43 | - 内存 44 | - 断点 45 | - 支持在内核态设置用户态程序的断点 46 | - 当前特权级 47 | - 本地变量 48 | - 自定义 GDB 语句 49 | - 自动加载符号信息文件 ![bg contain right:60%](./imgs/coredebugger-screenshot-bootstrap-mid.png) 50 | 51 | --- 52 | 53 | ## 调试工具设计与实现 54 | 55 | - 服务器 56 | - 用户端 57 | - 内核态用户态的断点冲突 ![bg contain right:60%](./imgs/arch-august.png) 58 | 59 | --- 60 | 61 | ## 服务器 62 | 63 | - 基于 `openvscode-server`提供网页版 vscode 64 | - 提供 qemu、rust 工具链、gdb 65 | - 自动编译、加载内核和 GDB ![bg contain right:60%](./imgs/arch-august.png) 66 | 67 | --- 68 | 69 | ## 符号信息的获取 70 | 71 | - `Cargo.toml`编译参数 72 | - `debug=true` 73 | - `opt-level=0` 74 | - 修改 easy-fs-fuse 75 | - `USER_HEAP_SIZE` 76 | - ... 77 | - `linker.ld` - 保留\*.debug 段 ![bg contain right:60%](./imgs/arch-august.png) 78 | 79 | --- 80 | 81 | ## Debug Adapter 82 | 83 | - 负责协调 VSCode 和 GDB 的独立进程。 84 | - 消息类型 85 | - Request 86 | - Response 87 | - Event 88 | - Debug Adapter Protocol - 大量 customRequest ![bg contain right:55%](./imgs/debug-arch1.png) 89 | 90 | --- 91 | 92 | ## 用户端 93 | 94 | - Extension Frontend - 消息监听与转发 - Debug UI - WebView 95 | ![bg contain right:55%](./imgs/debug-arch1.png) 96 | 97 | --- 98 | 99 | ## 内核态用户态的断点冲突 100 | 101 | - GDB 限制:无法在内核态设置用户态代码的断点 102 | - 可能与页表刷新有关 103 | - 解决思路:暂存断点,待时机合适再设置断点 104 | 105 | --- 106 | 107 | ## 断点组 108 | 109 | - 在内核即将进入用户态,以及 trap_handler 处设置断点 110 | - “进出口断点”被触发时清空断点,设置新断点 111 | - 缓存暂时无法设置的断点,待时机合适再设置 ![bg contain right:55%](./imgs/brk.png) 112 | - 扩展:内存信息也可以如此“切换“ 113 | 114 | --- 115 | 116 | ## 特权级切换处理 117 | 118 | - 切换符号表文件 119 | - `add-file` -> GDB 120 | - 切换断点组 121 | - 更新当前所在特权级 122 | - risc-v 处理器无寄存器能显示反映当前特权级 123 | - 借助“边界”断点、地址空间、文件名判断 124 | 125 | --- 126 | 127 | ## 局限 128 | 129 | - gdb 的 bug 130 | - Self 变量 131 | - Vec, VecDeque 132 | - 可查看但输出信息有误 133 | - lazy_static!宏 134 | - 被内联展开的函数 135 | 136 | --- 137 | 138 | ## 扩展 139 | 140 | - 支持其他 OS 141 | - 获取符号表信息(例如 vmlinux) 142 | - 确定内核“出入口”断点 143 | - 修改当前特权级判断逻辑 144 | - 修改断点组判断逻辑 145 | - 观察其他内核数据结构 146 | 1. 添加`customRequest`, 147 | 1. 收集数据:GDB 命令(mi2.ts) 148 | 1. 返回信息:Events/Responses 149 | 1. 插件进程解析 Events/Responses 并转发至 WebView(extension.ts) 150 | 1. 添加 WebView 界面(extension.ts) 151 | 152 | --- 153 | 154 | ## todos 155 | 156 | - 更多 os 157 | - 更多内核数据结构 158 | - 如进程控制块 159 | - WebView -> TreeView 160 | 161 | --- 162 | 163 | ## 项目仓库 164 | 165 | https://github.com/chenzhiy2001/code-debug 166 | 167 | --- 168 | 169 | ## 谢谢! 170 | 171 | --- 172 | -------------------------------------------------------------------------------- /pre-record/Slides-August.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/Slides-August.pdf -------------------------------------------------------------------------------- /pre-record/Slides-July.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/Slides-July.pdf -------------------------------------------------------------------------------- /pre-record/Slides-OSATC.md: -------------------------------------------------------------------------------- 1 | --- 2 | marp: true 3 | theme: default 4 | paginate: true 5 | _paginate: false 6 | header: "" 7 | footer: "" 8 | backgroundColor: white 9 | --- 10 | 11 | # code-debug 12 | 13 | 支持 Rust 语言的源代码级内核调试工具 14 | 15 | --- 16 | 17 | ## 项目背景与目标 18 | 19 | - rust 操作系统相关实验上手难度较高 20 | - 环境配置繁琐 21 | - GDB TUI 不方便 22 | - 近期目标 23 | - 基于 Qemu 的 rust 内核在线调试工具 24 | - 支持基于 eBPF 的单步断点、内存查看、寄存器查看功能 25 | - 内核态与用户态方便的切换跟踪 26 | - 远期目标 27 | - 基于真实系统(FPGA 或 RISC-V 开发板)的远程实验与调试系统 28 | - 提供低成本、开源的方案 29 | 30 | --- 31 | 32 | ## 在线调试系统 33 | 34 | - 类似 github classroom,浏览器打开即用 35 | - 调试者与被调试内核分离 36 | - VSCode 插件 37 | - 操作系统相关的调试功能 38 | - 配置方便 39 | - 可在单机上使用 docker 直接进行配置 40 | - 可通过配置 git 仓库路径自动下载其他版本 rust 内核代码进行测试 41 | - 目前以 rCore-Tutorial-V3 的 main 分支为默认版本 42 | 43 | --- 44 | 45 | ## 功能 46 | 47 | - 数据获取 48 | - 寄存器 49 | - 内存 50 | - 本地变量 51 | - 跟踪系统调用 52 | - 准确获取当前特权级 53 | - 支持在内核态设置用户态程序的断点 54 | - 自动加载、更换符号信息文件 55 | - 自定义 GDB 语句 56 | - 一键替换代码 ![bg contain right :50%](./imgs/coredebugger-screenshot-bootstrap-mid.png) 57 | 58 | --- 59 | 60 | ## 调试工具设计与实现 61 | 62 | 1. 支持 GDB 调试 63 | 2. 支持通过 VSCode 进行 GDB 调试 64 | 3. 解决内核态用户态的断点冲突 ![bg contain right:60%](./imgs/arch-august.png) 65 | 66 | --- 67 | 68 | ## 1. 支持 gdb 调试 69 | 70 | - 安装环境:qemu、rust、`riscv64-unknown-elf-gdb` 71 | - 关闭代码优化、保留符号信息 72 | - 自动编译、加载内核和 GDB 73 | - 接口:GDB/MI ![bg contain right:60%](./imgs/arch-august.png) 74 | 75 | --- 76 | 77 | ## 关闭代码优化、 保留符号信息 78 | 79 | - 修改 `cargo.toml` 配置文件中的编译参数 80 | - `debug=true` 保留调试信息 81 | - `opt-leve1=0` 最低优化等级 82 | - `linker.ld` 保留\*.debug 段 83 | - 修改后带来的问题 84 | - 应用程序占用的磁盘空问显著增加,导致 easy-fs-fuse(用于将应用程序打包为文件系统镜像)崩溃 85 | - 将磁盘镜像的空间调大 86 | - 用户栈溢出 87 | - 调整 `USER_STACK_SIZE` 等参数 88 | 89 | --- 90 | 91 | ## 2. 支持通过 VSCode 进行 GDB 调试 92 | 93 | 1. 支持 GDB 调试 94 | 2. 支持通过 VSCode 进行 GDB 调试 95 | 3. 解决内核态用户态的断点冲突 ![bg contain right:60%](./imgs/arch-august.png) 96 | 97 | --- 98 | 99 | ## 协调 VSCode 与 GDB 100 | 101 | - Debug Adapter 102 | - 负责协调 vSCode 和 GDB 的独立进程 103 | - 消息传送过程 (Debug Adapter Protocol) 104 | - Request-Response-Event 105 | - 基于 `code-debug` 实现 Debug Adapter 106 | - 没有查看寄存器、增删符号信息文件等调试操作系统所需的功能,通过 customRequest 添加 107 | ![bg contain right:55%](./imgs/debug-arch1.png) 108 | 109 | --- 110 | 111 | ## 实现用户端调试界面 112 | 113 | - Extension Frontend 114 | - 接收来自 DebugAdapter 的消息,发送用户的请求 115 | - Debug Ul 116 | - 与调试相关的用户界面。 117 | - Text Editor 118 | - 文本编辑窗口。用户在这个窗口内可以设置断点 ![bg contain right:55%](./imgs/vscode-scope.png) 119 | ![bg contain right:55%](./imgs/vscode-button.png) 120 | 121 | --- 122 | 123 | ## 3. 内核态用户态的断点冲突 124 | 125 | - GDB 限制:无法在内核态设置用户态代码的断点 126 | - 原因:特权级切换时,TLB 刷新 127 | - 解决思路:暂存断点,待时机合适再设置断点 128 | - 关键问题:暂存断点的策略,恢复断点的时机 ![bg contain right:55%](./imgs/border.png) 129 | 130 | --- 131 | 132 | ## 断点组管理模块 133 | 134 | - 分组缓存所有断点的信息 135 | - 当前断点组 136 | - 若用户设置的断点不属于当前断点组,不令 GDB 设置 137 | - 在特权级切换时切换符号表文件、进行断点组切换 138 | - 扩展:应用于多处理机、多线程、多协程… ![bg contain right:55%](./imgs/brk.png) 139 | 140 | --- 141 | 142 | ## 断点组切换 143 | 144 | - 时机:特权级切换 145 | - 行为:清除当前断点组的断点,设置新断点组的断点 146 | - 如何判断是否发生了特权级切换:在特权级切换的代码附近设置断点 147 | - rCore-Tutorial-v3 148 | - trap_handler 149 | - trap_return 150 | - 如果是别的内核代码,在内核即将进入用户态,以及用户态 trap 到内核态处设置断点 151 | - 这两个断点可以由 Debug Adapter 自动设置 152 | - 为何需要借助断点来更新特权级信息 153 | - risc-v 处理器无寄存器能显示反映当前特权级 154 | - 借助内存地址空间、边界断点、文件名判断 155 | 156 | --- 157 | 158 | ## 使用 eBPF 技术 159 | 160 | - 为了用上调试器,得改编译参数,改内核代码...比较繁琐 161 | - GDB 无法跟踪 rCore 的一些重要的内核数据结构,对 rust 语言的支持也不是特别好 162 | - 因此,我们想用 eBPF 技术来实现跟踪功能. 163 | - eBPF 技术使得用户可以在内核执行用户自定义的程序. 164 | 165 | --- 166 | 167 | ## 使用 eBPF 技术 168 | 169 | - 基本的思路是,用 eBPF 170 | 1. 设置断点,查看内存... 171 | 2. 提供一个 gdbserver 与外部的 gdb 通信 ![bg contain right:55%](./imgs/gdb-debug-method3.png) 172 | 173 | --- 174 | 175 | ## 项目仓库地址 176 | 177 | https://github.com/chenzhiy2001/code-debug 178 | 179 | --- 180 | 181 | ## 谢谢! 182 | 183 | --- 184 | -------------------------------------------------------------------------------- /pre-record/arch-eBPF-thoughts.md: -------------------------------------------------------------------------------- 1 | ## 概述 2 | 3 | 调试普通的用户态程序时,我们一般这么做: gdb 作为一个用户态程序,通过 ptrace 系统调用来控制同样处于 4 | 用户态的被调试的程序(debugee). 5 | 6 | ![图片](./imgs/gdb-traditional.png) 7 | 8 | 但是对于调试内核来说,这么做不太方便. 9 | 10 | 一些嵌入式设备这样调试:将 gdb 分解为 client 和 server,client 通过 TCP 协议连接到用户态的 gdbserver 11 | 上. ![图片](./imgs/gdbserver-embedded.png) 12 | 13 | [这篇文章](https://balau82.wordpress.com/2010/08/17/debugging-arm-programs-inside-qemu/)就使用了这个 14 | 方法: 15 | 16 | ![图片](./imgs/gdb-embedded-arm.png) 17 | 18 | 我们可以采用类似的思路. 19 | 20 | ## 第一种方案 21 | 22 | ![图片](./imgs/gdb-debug-method1.png) 23 | 24 | 需要做的工作有: 25 | 26 | 1. 增加 TCP/IP 协议栈 27 | 2. 参考这个[简单的 gdbserver 的实现](https://github.com/bet4it/gdbserver/blob/master/gdbserver.c)实 28 | 现 gdbserver. 主要的工作是把里面的 `ptrace()` 改成 kprobe 相关的系统调用,以及编写配套的 ebpf 程 29 | 序. 这个方案有两个缺点: 30 | 31 | 3. 需要增加网络协议栈,工作量较大 32 | 4. gdbserver 是持续在用户态运行的,可能会干扰到调试. 1. gdbserver 也可以持续在内核态运行(也就是一个 33 | 内核 task),但是也会干扰到调试因此我想到一种更简单的方案,就是把 gdbserver 放在内核的中断处理流 34 | 程里实现.这样做的优点有两个: 35 | 36 | 5. 不用增加网络协议栈 37 | 6. gdbserver 不持续运行,减小对调试的干扰 38 | 39 | ## 第二种方案 40 | 41 | ![图片](./imgs/gdb-debug-method2.png) 42 | 43 | 工作流程大致是这样的: 44 | 45 | 1. gdb 通过 qemu 的虚拟串口输入 tcp 报文。 46 | 2. 在 qemu 内的 os 里,串口输入产生中断。 47 | 3. os 的中断处理模块将这些报文转发给内核态的 gdbserver(只有此时它才运行,平时不运行)。 48 | 4. gdbserver 在内核态利用 kprobe 设置断点,收集内存数据等,并通过串口返回 tcp 报文. 然后 gdbserver 49 | 就不运行了,直到下次串口有输入。 gdbserver 的代码可以参 50 | 考[probe-rs](https://github.com/probe-rs/probe-rs). 51 | 52 | 这样的缺点是,需要对内核做大量改动。然而我们希望尽量减小调试工具和对某个具体内核的依赖。因此,考虑到 53 | eBPF 的高隔离性,我们可以将 gdbserver 完全用 ebpf 来实现. 54 | 55 | ## 第三种方案 56 | 57 | ![图片](./imgs/gdb-debug-method3.png) 58 | 59 | gdbserver 完全用 ebpf 程序来实现。可能要额外加一些帮助函数(helper function)。 60 | 61 | ## 第四种方案 62 | 63 | Debugger 和 eBPF 模块通过 SBI 进行通信 64 | 65 | ## 第五种方案 66 | 67 | 我发现[probe-rs](https://github.com/probe-rs/probe-rs)除了提供 gdbserver 的支持,还提供了 68 | 对[Debug Adapter](https://github.com/probe-rs/probe-rs#vscode)的支持. 因此,理论上我们可以去掉 gdb 69 | 和 gdbserver 这两个中间件,让插件和被调试的内核直接通信. 70 | -------------------------------------------------------------------------------- /pre-record/diff-rCore-Tutorial-Code-2023S-kernel.diff: -------------------------------------------------------------------------------- 1 | diff --git a/easy-fs-fuse/src/main.rs b/easy-fs-fuse/src/main.rs 2 | index bb9ff761..4568564f 100644 3 | --- a/easy-fs-fuse/src/main.rs 4 | +++ b/easy-fs-fuse/src/main.rs 5 | @@ -59,11 +59,11 @@ fn easy_fs_pack() -> std::io::Result<()> { 6 | .write(true) 7 | .create(true) 8 | .open(format!("{}{}", target_path, "fs.img"))?; 9 | - f.set_len(16 * 2048 * 512).unwrap(); 10 | + f.set_len(1600 * 2048 * 512).unwrap(); 11 | f 12 | }))); 13 | - // 16MiB, at most 4095 files 14 | - let efs = EasyFileSystem::create(block_file, 16 * 2048, 1); 15 | + // 1600MiB, at most 4095*100 files 16 | + let efs = EasyFileSystem::create(block_file, 1600 * 2048, 1); 17 | let root_inode = Arc::new(EasyFileSystem::root_inode(&efs)); 18 | let apps: Vec<_> = read_dir(src_path) 19 | .unwrap() 20 | diff --git a/os/Cargo.toml b/os/Cargo.toml 21 | index a93dc62a..97bb9420 100644 22 | --- a/os/Cargo.toml 23 | +++ b/os/Cargo.toml 24 | @@ -22,3 +22,8 @@ tinybmp = "0.3.1" 25 | 26 | [profile.release] 27 | debug = true 28 | +opt-level=0 29 | +# debuginfo-level = 1 30 | + 31 | +# Debuginfo level for the compiler. 32 | +# debuginfo-level-rustc = 2 33 | diff --git a/os/src/config.rs b/os/src/config.rs 34 | index 52839a3f..d4d8912d 100644 35 | --- a/os/src/config.rs 36 | +++ b/os/src/config.rs 37 | @@ -5,7 +5,7 @@ 38 | /// user app's stack size 39 | pub const USER_STACK_SIZE: usize = 4096 * 2; 40 | /// kernel stack size 41 | -pub const KERNEL_STACK_SIZE: usize = 4096 * 2; 42 | +pub const KERNEL_STACK_SIZE: usize = 4096 * 20; 43 | /// kernel heap size 44 | pub const KERNEL_HEAP_SIZE: usize = 0x200_0000; 45 | /// physical memory end address 46 | -------------------------------------------------------------------------------- /pre-record/diff-rCore-Tutorial-Code-2023S-user.diff: -------------------------------------------------------------------------------- 1 | diff --git a/.cargo/config b/.cargo/config 2 | index e5ded8a..867bffc 100644 3 | --- a/.cargo/config 4 | +++ b/.cargo/config 5 | @@ -3,5 +3,5 @@ target = "riscv64gc-unknown-none-elf" 6 | 7 | [target.riscv64gc-unknown-none-elf] 8 | rustflags = [ 9 | - "-Clink-args=-Tsrc/linker.ld", 10 | + "-Clink-args=-Tsrc/linker.ld","-Zunstable-options", 11 | ] 12 | diff --git a/Cargo.toml b/Cargo.toml 13 | index bdd5019..c99434e 100644 14 | --- a/Cargo.toml 15 | +++ b/Cargo.toml 16 | @@ -14,6 +14,9 @@ lock_api = "=0.4.6" 17 | lazy_static = { version = "1.4.0", features = ["spin_no_std"] } 18 | 19 | [profile.release] 20 | -opt-level = "z" # Optimize for size. 21 | -strip = true # Automatically strip symbols from the binary. 22 | -lto = true 23 | +debug=true 24 | +debuginfo-level = 1 25 | +debuginfo-level-rustc = 2 26 | +# opt-level = "z" # Optimize for size. 27 | +# strip = true # Automatically strip symbols from the binary. 28 | +# lto = true 29 | diff --git a/src/bin/ch9b_initproc.rs b/src/bin/ch9b_initproc.rs 30 | index 1e4011d..17bb3c7 100644 31 | --- a/src/bin/ch9b_initproc.rs 32 | +++ b/src/bin/ch9b_initproc.rs 33 | @@ -3,11 +3,14 @@ 34 | 35 | #[macro_use] 36 | extern crate user_lib; 37 | - 38 | +use user_lib::{println, getpid}; 39 | use user_lib::{exec, fork, wait, yield_}; 40 | 41 | #[no_mangle] 42 | fn main() -> i32 { 43 | + println!("aaaaaaaaaaaaaa"); 44 | + let a = getpid(); 45 | + println!("pid before fork is {}",a); 46 | if fork() == 0 { 47 | exec("ch7b_user_shell\0", &[core::ptr::null::()]); 48 | } else { 49 | diff --git a/src/lib.rs b/src/lib.rs 50 | index dc81cd8..26e6769 100644 51 | --- a/src/lib.rs 52 | +++ b/src/lib.rs 53 | @@ -18,7 +18,7 @@ use buddy_system_allocator::LockedHeap; 54 | pub use console::{flush, STDIN, STDOUT}; 55 | pub use syscall::*; 56 | 57 | -const USER_HEAP_SIZE: usize = 16384; 58 | +const USER_HEAP_SIZE: usize = 32768*4; 59 | 60 | static mut HEAP_SPACE: [u8; USER_HEAP_SIZE] = [0; USER_HEAP_SIZE]; 61 | 62 | diff --git a/src/linker.ld b/src/linker.ld 63 | index f3f996e..ef81405 100644 64 | --- a/src/linker.ld 65 | +++ b/src/linker.ld 66 | @@ -28,6 +28,5 @@ SECTIONS 67 | } 68 | /DISCARD/ : { 69 | *(.eh_frame) 70 | - *(.debug*) 71 | } 72 | } 73 | \ No newline at end of file 74 | -------------------------------------------------------------------------------- /pre-record/ebpf-ui.md: -------------------------------------------------------------------------------- 1 | # 调试器界面需求文档 2 | 3 | ## 功能 4 | 5 | ### 连接 6 | 7 | ``` 8 | |---------| 9 | | Connect | 10 | |_________| 11 | ``` 12 | 13 | 这个按钮用于连接到 rCore-Tutorial 里的 gdbserver。按下之后从插件获取串口的地址,然后在调试控制台中发 14 | 送一个命令`-side-stub connect 地址`。 15 | 16 | ### 符号查询 17 | 18 | ``` 19 | 应用程序列表 选中的应用程序的符号表 20 | -------------------------------- 21 | |Kernel |0x8020 rust_main| 22 | |App1 |0x0001 _start | 23 | |App2 |0x0010 main | 24 | |App3 |0xffff getpid | 25 | |.... |... ... | 26 | --------------------------------- 27 | ``` 28 | 29 | (VSCode WebView 不能直接访问本地文件,因此获取应用程序列表以及获取符号表的功能不在网页中实现,网页 30 | 里显示数据即可) 31 | 32 | ### 注册 uprobes/kprobes 33 | 34 | ``` 35 | ______________ 36 | Program Name:|_____________| 37 | _______________ 38 | Address: |_____________| 39 | 40 | ____________ 41 | | Register | 42 | ------------ 43 | ``` 44 | 45 | 这个界面的功能显而易见 46 | 47 | ## 用到的 API 48 | 49 | 1. [插件和 WebView 之间的交互](https://code.visualstudio.com/api/extension-guides/webview) 50 | 1. [输出内容到调试控制台](https://code.visualstudio.com/api/references/vscode-api#DebugConsole)(实际 51 | 上还得考虑输入内容到控制台,不过暂时没找到 API) 52 | -------------------------------------------------------------------------------- /pre-record/ebpf_vs_ptrace.md: -------------------------------------------------------------------------------- 1 | | | 基于 eBPF 的 gdbserver | 基于 ptrace 的 gdbserver | 2 | | -------------------- | -------------------------------- | --------------------------------------------------------------------- | 3 | | 读内存,读寄存器 | 可以 | 可以 | 4 | | 写内存,写寄存器 | 不行 | 可以 | 5 | | 进程控制块等内核信息 | 方便(因为有 helper function) | 麻烦(已经尝试很久) | 6 | | 停下(halt) | 不行 | 可以 | 7 | | 单步 | 不行(因为不能停下) | 可以 | 8 | | watchpoint | 不行(因为不能停下) | 可以 | 9 | | 跟踪函数调用关系 | 优点:查看函数调用的参数 | 优点:查看函数调用栈 | 10 | | 断点 | 由于不能停下,主要起辅助作用 | VSCode 插件的代码都基于一个前提:断点触发之后 os 会停下。因此必不可少 | 11 | | 跟踪异步函数 | 较方便(因为有 helper function) | 很麻烦 | 12 | -------------------------------------------------------------------------------- /pre-record/image/image-20230814224042999.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224042999.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224110164.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224110164.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224131871.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224131871.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224145315.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224145315.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224207165.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224207165.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224220270.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224220270.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224231835.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224231835.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224416817.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224416817.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224424724.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224424724.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224430651.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224430651.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224452355.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224452355.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224504863.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224504863.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224510933.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224510933.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224515641.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224515641.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224521448.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224521448.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224528153.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224528153.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224534802.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224534802.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224541472.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224541472.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224602068.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224602068.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224608979.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224608979.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224617880.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224617880.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224623546.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224623546.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224627053.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224627053.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224632667.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224632667.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224643271.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224643271.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224655298.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224655298.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224717507.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224717507.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224723030.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224723030.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224730754.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224730754.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224735588.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224735588.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224743741.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224743741.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224759724.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224759724.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224806930.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224806930.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224812301.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224812301.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224818236.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224818236.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224829324.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224829324.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224834373.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224834373.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224839246.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224839246.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224844219.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224844219.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224850295.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224850295.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224856529.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224856529.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224902769.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224902769.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224907727.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224907727.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224911662.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224911662.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224916020.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224916020.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224920706.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224920706.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224924064.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224924064.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224931754.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224931754.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224942613.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224942613.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814224947204.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814224947204.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814231257983.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814231257983.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814231311699.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814231311699.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814231318315.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814231318315.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814231327685.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814231327685.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814231334958.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814231334958.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814231342847.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814231342847.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814231358967.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814231358967.png -------------------------------------------------------------------------------- /pre-record/image/image-20230814231425659.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/image/image-20230814231425659.png -------------------------------------------------------------------------------- /pre-record/imgs/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/1.png -------------------------------------------------------------------------------- /pre-record/imgs/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/2.png -------------------------------------------------------------------------------- /pre-record/imgs/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/3.png -------------------------------------------------------------------------------- /pre-record/imgs/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/4.png -------------------------------------------------------------------------------- /pre-record/imgs/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/5.png -------------------------------------------------------------------------------- /pre-record/imgs/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/6.png -------------------------------------------------------------------------------- /pre-record/imgs/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/7.png -------------------------------------------------------------------------------- /pre-record/imgs/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/8.png -------------------------------------------------------------------------------- /pre-record/imgs/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/9.png -------------------------------------------------------------------------------- /pre-record/imgs/Debug-Adapter-Drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/Debug-Adapter-Drawio.png -------------------------------------------------------------------------------- /pre-record/imgs/DebugAdapter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/DebugAdapter.png -------------------------------------------------------------------------------- /pre-record/imgs/arch-220909.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/arch-220909.png -------------------------------------------------------------------------------- /pre-record/imgs/arch-august.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/arch-august.png -------------------------------------------------------------------------------- /pre-record/imgs/arch-with-ebpf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/arch-with-ebpf.png -------------------------------------------------------------------------------- /pre-record/imgs/arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/arch.png -------------------------------------------------------------------------------- /pre-record/imgs/async-msg.drawio: -------------------------------------------------------------------------------- 1 | 7Vldb5swFP01fqwUMBDnERK6PazStEhbu5fJBSegEBw5TpP0188GEz5M1nRlkG5Lper6GN/4nnuwrx0Ap+vDB4Y30R0NSQLMUXgAcAZME40m4r8EjjlgT2AOLFkc5tCoBObxM8lBo0B3cUi2CsshTmnC400dDGiakoDXMMwY3dcfW9AkrAEbvCQaMA9woqPf4pBHKixzXOIfSbyMim82HBXwGhcPq0i2EQ7pvgJBH8Apo5Tn1vowJYnkrs7L7Zne08QYSfklA36szE+j6Xfvyfvizkfjzd3X+4cb5eUJJzsVMDBtNV9+LEhgdJeGRPoZAejto5iT+QYHsncvsi6wiK8T0TKEuYiTZEoTyrKxMMQELQKBbzmjK1LpcQJEHheiR82BME4OZ4MzTpQJqRG6JpwdxSNqgDlSLBcyc1R7XybNUlBUyVeBYSWT5clzyaQwFJmvINbUiBWErQi/CTHH75Fg62WCDadPhmGLdKHG7DVyaV2bWC2NyiAiwWq7W78PPi/QJuqTT7tFmlanL/3Cln8Spymv4PmnlfDs0w3hkzrfjjWwfp3eFttheTfgy8SP+yS+qNL+euZt89qYb6vc9DXmXXF8bcuKoRdxHe2LwxLtXLCM9Lpfmm0b5huPIR3w1DxUDC5I8w9udF3wZb3MV79nhOKY/rZDQgfUNEv+4aWEOlvbuqDnAuX0uiJBvbDRaCFp6MobJtFKaSpAL8TbKHvfjDpD9ReRHGJ+X7EfKvbsUG0ci0YqYrqvNh6U56xRDspaxah8wiTULrgaWRFB0R0LyAULNMdsSfivtsz2NFfSaLekscAYSTCPn+rzbcut+obPNBaRlOWxcUZFhYs8TjXKrFyVNR05dUenyqRwlPOgOcqkdgr7DeprK+46Vp/xevUZQ6kPXag+a0j1WU5H6rONgdWnl73At4GYBZoC3wHuDLi2NDwHICQNZAD3FphOIhj1HpmwltKSo1wLIAv442y4A3wLeD5AnkRcJI2mrsUmwuv6xUm8TIUdCOEQUQ57cquJA5y4qmMdh6Ec7jGyjZ/xY+ZKanAjKcpIsz1gz6SvHafb/EcGQyuz1XtUrdUV1MEWd25tGuoACVvuT0W+vClA5v8s/3aWG/cEbVeR/aZZv9vN0oOAl+Ub3QIXAh/JhE1ghthZ4m2pgMlYdiFXacKzpQj+lVzC5p0P0nN5KjmqyYSvT6Zolr8E5gt5+XMq9H8C -------------------------------------------------------------------------------- /pre-record/imgs/border.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/border.png -------------------------------------------------------------------------------- /pre-record/imgs/brk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/brk.png -------------------------------------------------------------------------------- /pre-record/imgs/browser_os_multiple_tab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/browser_os_multiple_tab.png -------------------------------------------------------------------------------- /pre-record/imgs/browser_simplehttp_multiple_tab_bug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/browser_simplehttp_multiple_tab_bug.png -------------------------------------------------------------------------------- /pre-record/imgs/code-debug UI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/code-debug UI.png -------------------------------------------------------------------------------- /pre-record/imgs/coredebugger-screenshot-bootstrap-mid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/coredebugger-screenshot-bootstrap-mid.png -------------------------------------------------------------------------------- /pre-record/imgs/debug-arch1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/debug-arch1.png -------------------------------------------------------------------------------- /pre-record/imgs/framework.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/framework.png -------------------------------------------------------------------------------- /pre-record/imgs/gdb-debug-method1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/gdb-debug-method1.png -------------------------------------------------------------------------------- /pre-record/imgs/gdb-debug-method2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/gdb-debug-method2.png -------------------------------------------------------------------------------- /pre-record/imgs/gdb-debug-method3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/gdb-debug-method3.png -------------------------------------------------------------------------------- /pre-record/imgs/gdb-embedded-arm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/gdb-embedded-arm.png -------------------------------------------------------------------------------- /pre-record/imgs/gdb-traditional.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/gdb-traditional.png -------------------------------------------------------------------------------- /pre-record/imgs/gdbserver-embedded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/gdbserver-embedded.png -------------------------------------------------------------------------------- /pre-record/imgs/messageFlow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/messageFlow.png -------------------------------------------------------------------------------- /pre-record/imgs/new-Coredebugger-APIs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/new-Coredebugger-APIs.png -------------------------------------------------------------------------------- /pre-record/imgs/pre-2022-07-24.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/pre-2022-07-24.mp4 -------------------------------------------------------------------------------- /pre-record/imgs/pre.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/pre.mp4 -------------------------------------------------------------------------------- /pre-record/imgs/pre_with_sub.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/pre_with_sub.mp4 -------------------------------------------------------------------------------- /pre-record/imgs/text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/text.png -------------------------------------------------------------------------------- /pre-record/imgs/vscode-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/vscode-button.png -------------------------------------------------------------------------------- /pre-record/imgs/vscode-scope.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/imgs/vscode-scope.png -------------------------------------------------------------------------------- /pre-record/memory-read-write.md: -------------------------------------------------------------------------------- 1 | ## 内存查看、编辑功能实现说明 2 | 3 | 目前,调试工具已经支持使用微软官方的 HexEdit 插件对内存指定地址数据进行显示和编辑,本文档主要介绍实 4 | 现该功能的原理,以方便后续维护和升级。 5 | 6 | ## 之前内存访问的方式 7 | 8 | 在本项目的 upstream 仓库中,已经具备了在调试插件中查看内存数据的功能,但在该功能实现时,DAP 中并没有 9 | 关于内存读写的相关协议存在,因此使用了一个绕弯的方式来实现该功能,及 DebugAdapter 进程中启动了一个本 10 | 地的 socket 服务器,在 Extension 进程中连接该服务器,相当于在 DAP 本身的 RPC 之外,又开辟了一条独立 11 | 的 RPC 信道。通过这条新的信道,可以实现内存数据读取的功能,读取到的数据通过一个自定义的 12 | ContentProvider 进行数据格式化,然后显示在窗口中。 13 | 14 | 该实现有如下问题: 15 | 16 | - 使用了一个独立的 Socket,增加了程序的复杂性,同时还需要用户选择不同会话之间对应的 Socket 连接,易 17 | 用性很差。 18 | - 仅支持内存查看,不支持实时修改 19 | 20 | ## 开源社区已有的前置工作 21 | 22 | ### Debug Apapter Protocol 引入 23 | 24 | DAP 的 1.35 版本,引入了 readMemory 请求,在 1.48 版本引入了 writeMemory 请求。这两个请求使得通过标 25 | 准 DAP 协议进行内存读取和修改成为了可能。 26 | 27 | ### VSCode 支持 DAP 的 readMemory、writeMemory 请求 28 | 29 | 在 https://github.com/microsoft/vscode/pull/133643 这个 PR 中,VSCode 引入了对内存操作的支持,重点如 30 | 下: 31 | 32 | - 定义了新的 schema`vscode-debug-memory`,并且将其关联到一个实现了虚拟文件系统接口的 33 | 类`DebugMemoryFileSystemProvider`上。 34 | 35 | - 这也就意味着,如果打开一个 URL 以`vscode-debug-memory://`开头的文档,那么 VSCode 会调 36 | 用`DebugMemoryFileSystemProvider`这个虚拟文件系统类来提供要显示的文件的内容。这个虚拟文件系统会 37 | 解析文件 URL 中的其他参数(比如要访问的内存地址、读取数据的长度等等),创建出一个虚拟的文件描述 38 | 符,并将文件的 read 请求自动翻译成 DAP 中的 readMemory 请求,将文件的 write 请求自动翻译为 DAP 协 39 | 议中的 writeMemory 请求。 40 | 41 | - 通过调用微软自己开发的另一款名为 HexEdit 的插件,来实现对内存的查看和编辑。 42 | - 具体来说,这个版本的 VSCode 引入了在调试模式界面下,在变量列表窗口中,每个变量的后面会出现一个查 43 | 看内存数据的小图标,点击某个变量后面的这个小图标时,VSCode 就会自动调用 HexEdit 插件来打开该变量 44 | 内存所在地址的虚拟文件,这样就可以在 HexEdit 中查看编辑了。 45 | 46 | ### 微软的 HexEdit 插件 47 | 48 | 这是微软提供的一个十六进制查看、编辑的插件,可以以 16 进制和 ASCII 视图打开一个文件并进行编辑。 49 | 50 | 上面提到了,由于这个插件是微软官方开发的,和 VSCode 本身的代码联系还是很紧密的,因此这个插件里面包含 51 | 针对 memory debug 的特殊支持, 引入这些特殊支持的提交是 52 | :https://github.com/microsoft/vscode-hexeditor/commit/5f742bd946356718de41aacd3d6ac00e15a0cb85 53 | 54 | ## 我的工作 55 | 56 | 1. 梳理清楚了上述各个前置工作之间的关联关系 57 | 58 | 1. 在`mibase.ts`中实现了`readMemoryRequest` 和 `writeMemoryRequest`两个方法的实现,将 DAP 的请求翻译 59 | 成 GDB 的对应指令。 60 | 61 | 1. 删除了上游仓库中陈旧的实现方式,完全迁移到标准的 DAP 协议上,精简了代码 62 | 63 | 1. 修改`code-debug.examineMemoryLocation`命令的实现逻辑,由用户输入需要查看的内存地址范围以后,自动 64 | 调用 HexEdit 插件来显示或编辑内存数据 65 | 66 | ## 后续展望 67 | 68 | - 目前,HexEdit 还是一个独立的插件,这个插件所提供的十六进制编辑视图本身并没有集成到 VSCode 中,但是 69 | 社区也在讨论后续是否会将这个视图内置到 VSCode 中。这个点可以跟进关注 70 | 71 | - 在融合到 VSCode 之前,我们的插件如果想使用内存查看、编辑功能,就必须首先安装好 HexEdit 插件,可 72 | 以引入自动检测功能,如果发现当前还没有安装 HexEdit 插件,那么提示用户安装。 73 | 74 | - 由于我们目前的插件还不支持在调试窗口的 TreeView 中显示本地变量等,因此也就没有办法使用 VSCode 本身 75 | 已经集成的查看变量内存的功能。期望在后续把 WebView 完全替换成 TreeView 以后,就可以多一种查看内存 76 | 的操作入口。 77 | 78 | - 目前,虚拟文件系统和 HexEdit 之间对异常的传递不是很友好,如果 GDB 在读取内存过程中发生错误,这个错 79 | 误不能经由虚拟文件系统传递给 HexEdit,这会导致当底层发生错误时,HexEdit 窗口无法体现出错情况。 80 | -------------------------------------------------------------------------------- /pre-record/mid.md: -------------------------------------------------------------------------------- 1 | # 5-15 阶段性技术报告 2 | 3 | ## 前期调研情况 4 | 5 | 确定了基本功能: 6 | 7 | - 关键的寄存器和内存的数据获取 8 | - 特树级信息的准确获取 9 | - 在 USM 三态修改符号表,并获取内存单元信息 10 | 11 | ## 导师沟通情况 12 | 13 | 已经与校内导师和项目导师取得联系,沟通良好 14 | 15 | ## 当前的开发状态 16 | 17 | - 插件已经支持即时更新: 18 | - 内存信息 19 | - 寄存器信息(包括通用寄存器和 CSR) 20 | - 特权级信息 21 | 22 | ## 下一步预期规划 23 | 24 | - 特权级信息准确获取 25 | - 提供更友好的用户界面 26 | - 支持用户态程序的跟踪 27 | 28 | ## 困难/需要得到的帮助 29 | 30 | - vscode 的插件开发资料不够详细,一些 api 未详细说明用法 31 | - 希望更多人来试用,给我们改进的建议 32 | -------------------------------------------------------------------------------- /pre-record/multiple_stubs.md: -------------------------------------------------------------------------------- 1 | # VScode 同时连接被跟踪操作系统的 OpenOCD 和 eBPF 的实施方案 2 | 3 | 我们跟踪的目标(target)是同一个,但是通过两种跟踪技术同时跟踪。我们把会改变操作系统状态的那个跟踪技 4 | 术(Qemu 的 gdbserver 或 OpenOCD)称为 main-stub,eBPF 的 GDBServer 称为 side-stub。 Main-stub 负责 5 | 控制,而 side-stub 只负责收集信息,不能影响内核的状态。 6 | 7 | 在使用流程上,二者的区别在于,ebpf server 要提前指定要做的事。具体如下: 8 | 9 | main-sub 的流程: 10 | 11 | 1. 设置断点 12 | 1. **断点触发,os 暂停运行** 13 | 1. GDB 等待用户输入命令,根据用户的命令执行信息收集,改变 os 状态等行为 14 | 15 | side-stub 的流程: 16 | 17 | 1. 设置断点,**提前指定断点触发后的操作**。 18 | 1. os 注册相关的 ebpf 程序 19 | 1. 断点触发,eBPF 程序执行这些操作,返回信息,os 继续运行。 20 | 21 | 二者是可以同时存在的。在具体实现方面,最方便的方式是利用 python 脚本注册新的 gdb 命令(我打算直接叫 22 | 它`side-stub`)。这样的好处有两个,一是不需要改动 gdb 的源代码,二是 VSCode 端不需要做大幅度的调整, 23 | 现有的断点组切换等功能无需改动,只要支持一个新的 gdb 命令即可。 24 | 25 | 对于这个新的 gdb 命令的初步构想: 26 | 27 | ``` 28 | // 连接到ebpf server的串口. 29 | // python脚本负责向串口发送信息. 30 | // python脚本接收到的信息会返回给gdb. 31 | side-stub target remote /dev/tty1 32 | ``` 33 | 34 | ``` 35 | // 在某地址设置断点,然后收集寄存器信息 36 | side-stub break 0x8020xxxx then-get register-info 37 | ``` 38 | 39 | ``` 40 | // 收集函数参数 41 | side-stub arguments 42 | ``` 43 | 44 | 此外还要琢磨一个事,编译的时候,符号信息应该单独提取出来,提供给 gdb,由 gdb 做符号解析,看看能否做 45 | 到不用修改内核编译参数。 46 | 47 | 控制相关的功能有: 48 | 49 | - 断点 50 | - 单步 51 | - 设置寄存器 52 | - 设置内存 53 | 54 | 监测相关的功能有: 55 | 56 | - 符号转地址(这个虽然可以在 ebpf 中做,但也可以在 gdb 上做) 57 | - 查看寄存器 58 | - 查看内存 59 | -------------------------------------------------------------------------------- /pre-record/oscomp-final.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/oscomp-final.pptx -------------------------------------------------------------------------------- /pre-record/oscomp_share17_rust_debugger.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/oscomp_share17_rust_debugger.pptx -------------------------------------------------------------------------------- /pre-record/pcb_name.md: -------------------------------------------------------------------------------- 1 | # 怎么保留进程的名字信息 2 | 3 | ProcessControlBlock 有四个函数: new() 用于创建 initproc. 此处的修改很简单: fork() 用于 fork. 这个 4 | 也很简单,fork 的时候添加一个参数就行。因为 fork 前后,名字是保持不变的。如果 fork 后再 exec 情况就 5 | 不一样了。具体可以看下一节。: exec() 略微复杂。首先我们要明白 exec()干什么: In computing, exec is 6 | a functionality of an operating system that runs an executable file in the context of an already 7 | existing process, replacing the previous executable. This act is also referred to as an overlay. 也 8 | 就是说, exec() 覆盖了现有的资源,不会创造新的进程控制块。因此,在 exec()中,我们直接更改当前进程的 9 | path 信息: 10 | 11 | 下面这个是错误的结论。exec()如果成功执行的话,是不会返回的。initproc.rs 里面有两个 exec()是因为,如 12 | 果第一个执行失败了,还有第二个 exec 兜底。代码: ~~此外还有个容易忽略的地方:exec()函数会返回到原来 13 | 的函数继续执行,因此,我们要在“返回到原来的函数继续执行”这个流程中,恢复 exec()前的 path. 否则,在调 14 | 用 exec()后 path 就不正确了,这是一个容易忽略的地方。查 rCore-Tutorial-v3 文档得到函数是 (注意这个 15 | 不是调度用的那个 idle 函数):~~ 16 | 17 | 我发现一边写代码一边写文档效率是比较高的。如果事后写文档的话,回忆起来很累,而且回忆得不完整。 18 | -------------------------------------------------------------------------------- /pre-record/port-to-hardware.md: -------------------------------------------------------------------------------- 1 | ## 参考对象 2 | 3 | [Cortex-Debug](https://github.com/Marus/cortex-debug) 是一个 VSCode 的 OpenOCD 调试插件,它和我们这 4 | 个插件一样,都是由 [WebFreak001/code-debug](https://github.com/WebFreak001/code-debug) 修改而来的。 5 | 所以其中很多代码和我们的是相似的 6 | 7 | ## 移植思路 8 | 9 | 1. launch.json 里面的 qemu 启动参数改成启动 openocd 的 10 | 2. 找到 Alien OS 的 trap_handler,修改之前折腾的那三个行号 11 | 3. 找到这个 OS 的存放用户应用程序的位置,然后再略微修改源代码里面相关的部分(extension.ts 或 12 | mibase.ts),最好直接把可以提取的参数给提取出来到 launch.json 里 13 | 14 | ## 资料 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /pre-record/port.md: -------------------------------------------------------------------------------- 1 | ## 必须的依赖 2 | 3 | 1. ebpf 支持 4 | 1. 符号表 5 | 1. risc-v 工具链提供的 gdb 6 | 7 | ## 配置 8 | 9 | 1. launch.json 10 | 1. `code-debug/src/frontend/extension.ts` 硬编码的用户程序名,硬编码的 rCore 位置 11 | 1. 15 行 initproc 改成 ch9b_initproc 12 | 2. 16 行改成您要 debug 的 rCore 的位置,比如 os.homedir() + "/rCore-Tutorial-Code-2023S" 13 | 1. `code-debug/src/mibase.ts` 硬编码的行号 14 | 1. 1255 行,65 改成 79 15 | 2. 1264 行和 343 行,135 改成 148 16 | 3. 1281 行,30 改成 43 17 | 1. 改内核编译参数 18 | 1. code-debug/src/frontend/extension.ts 中的 16 行改成您要 debug 的 rCore 的位置,比如 19 | os.homedir() + "/rCore-Tutorial-Code-2023S" 20 | -------------------------------------------------------------------------------- /pre-record/rCore-mod-older.md: -------------------------------------------------------------------------------- 1 | 这是旧的截图版本,别用 ![1](./imgs/1.png) ![2](./imgs/2.png) ![3](./imgs/3.png) ![4](./imgs/4.png) 2 | ![5](./imgs/5.png) ![6](./imgs/6.png) ![7](./imgs/7.png) ![8](./imgs/8.png) ![9](./imgs/8.png) 3 | ![10](./imgs/9.png) 4 | -------------------------------------------------------------------------------- /pre-record/rCore-mod.diff: -------------------------------------------------------------------------------- 1 | diff --git a/easy-fs-fuse/src/main.rs b/easy-fs-fuse/src/main.rs 2 | index bb9ff761..e1dd2683 100644 3 | --- a/easy-fs-fuse/src/main.rs 4 | +++ b/easy-fs-fuse/src/main.rs 5 | @@ -59,11 +59,11 @@ fn easy_fs_pack() -> std::io::Result<()> { 6 | .write(true) 7 | .create(true) 8 | .open(format!("{}{}", target_path, "fs.img"))?; 9 | - f.set_len(16 * 2048 * 512).unwrap(); 10 | + f.set_len(1600 * 2048 * 512).unwrap(); 11 | f 12 | }))); 13 | - // 16MiB, at most 4095 files 14 | - let efs = EasyFileSystem::create(block_file, 16 * 2048, 1); 15 | + // 1600MiB, at most 409500 files 16 | + let efs = EasyFileSystem::create(block_file, 1600 * 2048, 1); 17 | let root_inode = Arc::new(EasyFileSystem::root_inode(&efs)); 18 | let apps: Vec<_> = read_dir(src_path) 19 | .unwrap() 20 | diff --git a/os/Cargo.toml b/os/Cargo.toml 21 | index fde4b6cb..e756e6d9 100644 22 | --- a/os/Cargo.toml 23 | +++ b/os/Cargo.toml 24 | @@ -23,3 +23,8 @@ sbi-rt = { version = "0.0.2", features = ["legacy"] } 25 | 26 | [profile.release] 27 | debug = true 28 | +opt-level=0 29 | +# debuginfo-level = 1 30 | + 31 | +# Debuginfo level for the compiler. 32 | +# debuginfo-level-rustc = 2 33 | diff --git a/os/src/config.rs b/os/src/config.rs 34 | index 8f8b709a..cb668f62 100644 35 | --- a/os/src/config.rs 36 | +++ b/os/src/config.rs 37 | @@ -1,7 +1,7 @@ 38 | #[allow(unused)] 39 | 40 | pub const USER_STACK_SIZE: usize = 4096 * 2; 41 | -pub const KERNEL_STACK_SIZE: usize = 4096 * 2; 42 | +pub const KERNEL_STACK_SIZE: usize = 4096 * 20; 43 | pub const KERNEL_HEAP_SIZE: usize = 0x100_0000; 44 | pub const MEMORY_END: usize = 0x88000000; 45 | pub const PAGE_SIZE: usize = 0x1000; 46 | diff --git a/user/.cargo/config b/user/.cargo/config 47 | index 334d01e2..4c8362eb 100644 48 | --- a/user/.cargo/config 49 | +++ b/user/.cargo/config 50 | @@ -3,5 +3,5 @@ target = "riscv64gc-unknown-none-elf" 51 | 52 | [target.riscv64gc-unknown-none-elf] 53 | rustflags = [ 54 | - "-Clink-args=-Tsrc/linker.ld", "-Cforce-frame-pointers=yes" 55 | + "-Clink-args=-Tsrc/linker.ld", "-Cforce-frame-pointers=yes","-Zunstable-options", 56 | ] 57 | diff --git a/user/Cargo.toml b/user/Cargo.toml 58 | index 1d7b2efc..194edad0 100644 59 | --- a/user/Cargo.toml 60 | +++ b/user/Cargo.toml 61 | @@ -16,4 +16,6 @@ oorandom ="11" 62 | virtio-input-decoder = "0.1.4" 63 | 64 | [profile.release] 65 | -debug = true 66 | +debug=true 67 | +debuginfo-level = 1 68 | +debuginfo-level-rustc = 2 69 | diff --git a/user/src/bin/initproc.rs b/user/src/bin/initproc.rs 70 | index d25aee14..d49f05d3 100644 71 | --- a/user/src/bin/initproc.rs 72 | +++ b/user/src/bin/initproc.rs 73 | @@ -3,10 +3,20 @@ 74 | 75 | extern crate user_lib; 76 | 77 | +use user_lib::{println, getpid}; 78 | + 79 | use user_lib::{exec, fork, wait, yield_}; 80 | 81 | #[no_mangle] 82 | fn main() -> i32 { 83 | + 84 | + 85 | + println!("aaaaaaaaaaaaaa"); 86 | + let a = getpid(); 87 | + println!("pid is {}",a); 88 | + 89 | + 90 | + 91 | if fork() == 0 { 92 | exec("user_shell\0", &[core::ptr::null::()]); 93 | } else { 94 | diff --git a/user/src/lib.rs b/user/src/lib.rs 95 | index bda0e8b6..1668cba1 100644 96 | --- a/user/src/lib.rs 97 | +++ b/user/src/lib.rs 98 | @@ -27,7 +27,7 @@ pub use sync::*; 99 | use syscall::*; 100 | pub use task::*; 101 | 102 | -const USER_HEAP_SIZE: usize = 32768; 103 | +const USER_HEAP_SIZE: usize = 32768*4; 104 | 105 | static mut HEAP_SPACE: [u8; USER_HEAP_SIZE] = [0; USER_HEAP_SIZE]; 106 | 107 | diff --git a/user/src/linker.ld b/user/src/linker.ld 108 | index 02f7b6bf..1df4e67e 100644 109 | --- a/user/src/linker.ld 110 | +++ b/user/src/linker.ld 111 | @@ -27,6 +27,5 @@ SECTIONS 112 | } 113 | /DISCARD/ : { 114 | *(.eh_frame) 115 | - *(.debug*) 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /pre-record/rcore学习文档.md: -------------------------------------------------------------------------------- 1 | **2023.1.1\~2023.3.1** 2 | 3 | 此阶段目标:学习 rcore 操作系统 4 | 5 | 下面是遇到的一些问题,以聊天记录的形式呈现 6 | 7 | 向驹韬:学长,我想请教你几个问题 8 | 9 | ![image-20230814224042999](image\image-20230814224042999.png) 10 | 11 | 向驹韬:这一段代码的功能是按地址分别分配 text rodata data bss 段 12 | 13 | ![image-20230814224110164](image\image-20230814224110164.png) 14 | 15 | 向驹韬:这一小段中,第二行的\*(.text.entry)我知道是载入 entry.asm 代码,可是下一行的\*(.text 16 | .text.\*)是什么意思呢? 17 | 18 | 向驹韬:还有就是 为什么这 text 段不像后面三段一样,加上\*(.stext .stext.\*)呢? 19 | 20 | 向驹韬:以上是第一个问题 谢谢学长啦 21 | 22 | 向驹韬:![image-20230814224131871](image\image-20230814224131871.png) 23 | 24 | 向驹韬: 25 | 26 | 这里是不是相当于是 27 | 28 | for(a=sbss;a\ 58 | 59 | 向驹韬:好的 谢谢学长! 60 | 61 | 向驹韬: 62 | 63 | ![image-20230814224207165](image\image-20230814224207165.png) 64 | 65 | 向驹韬:学长,你看这段话我这样理解对吗:trap 上下文就是寄存器集合,里面存了应用程序的地址等信息。先 66 | 把这些信息保存进内核栈,然后 trap 会对寄存器进行修改,等 trap 处理完之后,就从内核栈里把寄存器们复原 67 | ,从而让应用程序接着上次的地址运行。 68 | 69 | 向驹韬:这段话来自文档第二章的"实现特权级的切换" 70 | 71 | 陈志扬:对的 就是这样 72 | 73 | 陈志扬:那个\_alltraps 是汇编写的,就是干这些事 74 | 75 | 向驹韬: 76 | 77 | ![image-20230814224220270](image\image-20230814224220270.png) 78 | 79 | 向驹韬:这段代码是用来加载多道程序的 80 | 81 | 向驹韬:18 行之前我能看懂 就是对 app_num 进行修改,然后给每个程序分配一块空间并且初始化 82 | 83 | 向驹韬:但是我不知道 18 行之后,他是怎么做到把应用程序加载到空间里的 84 | 85 | 向驹韬:我尤其不太懂 23 行,app_start 不是一个用来修改 app_num 的函数吗?咋还有数组和减法 86 | 87 | 陈志扬:app_start 是数组啊,你看第七行,from_raw_parts 返回的是数组 88 | 89 | 陈志扬:"from_raw_parts 返回的是数组",这个说的不太准确,我的理解是,from_raw_parts 是把实际存在的数 90 | 组转换为语义上的数组 91 | 92 | 向驹韬:那这个数组里存的是什么啊,还是说只是单纯的创建了一个数组,然后在创建的时候调用了 add 函数并 93 | 让 numapp+1 吗 94 | 95 | 陈志扬:那个数组在这,第二章里面有写 96 | 97 | 向驹韬:哦哦哦我明白了 后面那两个是 from raw parts 的两个参数,形成了一个切片,里面有应用程序的地址 98 | ,是这样吗 99 | 100 | 陈志扬:对 101 | 102 | 向驹韬: 103 | 104 | ![image-20230814224231835](image\image-20230814224231835.png) 105 | 106 | 向驹韬:请问一下这段代码的作用是把 usize 类型的物理地址和物理页号转化为真正的物理地址和物理页号吗? 107 | 108 | 陈志扬:真正的物理地址和物理页号也是 usize 类型的呀,只是做了取前几位的处理而已 109 | 110 | 向驹韬:换句话说,就是用 usize 类型的话,内核不能识别,需要这个函数来转化一下,从而变得可识别吗 111 | 112 | 陈志扬:对的 113 | 114 | 向驹韬:另外就是,这里的 v & ( (1 \<\< PA_WIDTH_SV39) - 1 )我不明白是什么意思 115 | 116 | 陈志扬:这个的作用其实就是取后 56 位 117 | 118 | 1 \<\< PA_WIDTH_SV39 == 1000000\.....(共 56 个 0) 119 | 120 | (1 \<\< PA_WIDTH_SV39 -1 ) == 011111111\....(共 56 个 1) 121 | 122 | v 和 ( (1 \<\< PA_WIDTH_SV39) - 1 ) 按位与,就可以取前 56 位了 123 | 124 | 向驹韬:好的谢谢 125 | -------------------------------------------------------------------------------- /pre-record/thesis-2023-july.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | 断点组切换 4 | 5 | ## eBPF+GDB 静态动态跟踪 6 | 7 | ## uprobe 模块化 8 | 9 | ### uprobe 原理(参考 pcy 的图,结合实际代码来写,加上最近的 commit(即解释 commit)) 10 | 11 | ### 移植细节 12 | 13 | 专门提出去一个库 14 | 15 | ### rCore-Tutorial 的双页表设计带来的问题-参考 os_copy_from_data 代码和相关日志写. 16 | 17 | ### 详细的 migration 流程 18 | 19 | ### 例子 20 | 21 | ## 软硬件结合 22 | -------------------------------------------------------------------------------- /pre-record/thesis-outline.md: -------------------------------------------------------------------------------- 1 | 1. eBPF 技术简介(怎么用 eBPF 技术获取信息(kprobe),存储信息,用 eBPF 的优势) 2 | 2. gdbserver 协议, gdbserver 和 eBPF server 的不同(eBPF-server 以异步的消息为主。异步的消息和同步的 3 | 消息重合了怎么办(%)) 4 | 3. 用 gdb 的 python 扩展(重新编译) 5 | 4. py 脚本的编写(另一个线程) 6 | 5. qemu 支持新串口(为什么要用第二个串口,pmp,基于中断的串口消息收发机制(正是因为这个机制,消息不 7 | 能返回 server,而是直接由 eBPF 程序返回),qemu virtio) 8 | 9 | 没写的内容: ebpf 实现:移植,升级,对 eBPF 以外的符号信息的依赖; 10 | 11 | eBPF lambda 图 helpers 12 | -------------------------------------------------------------------------------- /pre-record/treeview.md: -------------------------------------------------------------------------------- 1 | # 将 WebView 迁移到 TreeView 2 | 3 | > Author: werifu 4 | > 5 | > Data: 2022.09.09 6 | 7 | ## 变动介绍 8 | 9 | 原本基于 WebView 的调试器架构如下: 10 | 11 | ![](./imgs/new-Coredebugger-APIs.png) 12 | 13 | 要将数据展示给用户,需要创建一层 WebView 的视图,通过 14 | 15 | 1. 向 VSCode 发送信息 16 | 2. VSCode 向调试器(Debug Adapter,在 code-debug 里作为一个 DebugSession 存在)发送请求,即 17 | sendRequest 18 | 3. DA 向 gdb 发送命令,即 sendCommand 19 | 4. dgb 向 DA 返回 MI 格式的命令 20 | 5. DA 向 VSCode 发送响应,即 sendResponse 21 | 6. VSCode 向 WebView 发送消息 22 | 7. WebView 通过事件监听获得消息并渲染数据 23 | 24 | 这样的链路来实现信息的传递,这样做有比较高的自由度,但是忽略了 VSCode 本身就有 debugger 界面的支持, 25 | 因此最外层 WebView 与 VSCode 的交互会显得比较冗余,因此优化方案是使用 TreeView 来完全取代 WebView 的 26 | 功能,使其更像一个 debugger,提高用户体验。 27 | 28 | 修改后的架构如下 29 | 30 | ![](imgs/arch-220909.png) 31 | 32 | mibase 与更底层的架构没有变化,这里只是画得更精简。 33 | 34 | ## 数据展示(输出) 35 | 36 | 核心是我们砍掉了 WebView 与 VSCode 的交互,那我们如何展示数据? 37 | 38 | VSCode 其实提供了几个重要的原生 request 接口,如 variablesRequest,其功能是展示 debugger 页中,左边 39 | VARIABLES 中变量的名字与值。每当 VSCode 的代码调试发生了暂停,VSCode 都会自动发送一个 40 | variablesRequest 向 DA 请求变量数据,那么我们只需要实现自定义的 variablesRequest,就可以做到自定义数 41 | 据,如下我们可以在 TreeView 里展示寄存器 42 | 43 | ![](imgs/vscode-scope.png) 44 | 45 | ## 命令发送(输入) 46 | 47 | 前面【数据展示】讲的是输出方面的,这节介绍输入的变动,WebView 的另一个功能是实现命令按钮,比如点一下 48 | 删除全部断点等等,如何直接做到 VSCode 里? 49 | 50 | 每个文件打开时右上角常常可以看到按钮,这些也是可自定义编辑的 51 | 52 | ![](imgs/vscode-button.png) 53 | 54 | 点击按钮理应产生一个命令,我们往 package.json 的 contributes.commands 中注册命令,即可 55 | 56 | ```json 57 | { 58 | "commands": [ 59 | { 60 | "command": "code-debug.removeAllCliBreakpoints", 61 | "title": "Remove All Cli Breakpoints", 62 | "icon": { 63 | "dark": "images/remove-all-cli-breakpoints-dark.svg", 64 | "light": "images/remove-all-cli-breakpoints-light.svg" 65 | } 66 | } 67 | ] 68 | } 69 | ``` 70 | 71 | 之后注册按钮,按钮在 package.json 的 contributes.menus 中注册,不同区域位于不同的 menu 中,其中右上 72 | 角所在的位置为 editor/title,当 group 为 navigation 时会显示在右上,否则折叠起来在最右上角的 `···` 73 | 中 74 | 75 | ```json 76 | { 77 | "menus": [ 78 | "editor/title": [ 79 | { 80 | "when": "resourceLangId == rust", 81 | "command": "code-debug.removeAllCliBreakpoints", 82 | "group": "navigation" 83 | } 84 | ] 85 | ] 86 | } 87 | ``` 88 | 89 | ## 尚未完成 90 | 91 | - 对于变量的数据展示 92 | 93 | - 现在都是使用 \ 占位 94 | 95 | - watchpoint 支持 96 | - 通过代码为 VSCode 视图加断点 97 | - 研究了很多文档与问答,发现 VSCode 确实无法支持此功能,没有提供 API 98 | -------------------------------------------------------------------------------- /pre-record/开发记录和知识库.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/开发记录和知识库.pdf -------------------------------------------------------------------------------- /pre-record/最终报告.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/最终报告.pdf -------------------------------------------------------------------------------- /pre-record/泉城集中开发-陈志扬.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/泉城集中开发-陈志扬.pdf -------------------------------------------------------------------------------- /pre-record/泉城集中开发-陈志扬.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/泉城集中开发-陈志扬.pptx -------------------------------------------------------------------------------- /pre-record/演示视频.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/演示视频.mp4 -------------------------------------------------------------------------------- /pre-record/答辩PPT.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/答辩PPT.pptx -------------------------------------------------------------------------------- /pre-record/陈志扬-OSATC-20230325-1807.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chenzhiy2001/code-debug/c102c48714221e5a38d28a54289080fff7ca0892/pre-record/陈志扬-OSATC-20230325-1807.pdf --------------------------------------------------------------------------------