I'm debugging v8 using lldb.
How can I print the string inside of Handle<String> Source?
The debug process is as follows:
(lldb) r
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1
frame #0: 0x000000010100536b libv8.dylib`v8::internal::Compiler::GetSharedFunctionInfoForScript(isolate=0x0000000118008000, source=Handle<v8::internal::String> # 0x00007ffeefbfd4a0, script_details=0x00007ffeefbfd730, origin_options=(flags_ = 0), extension=0x0000000000000000, cached_data=0x0000000000000000, compile_options=kNoCompileOptions, no_cache_reason=kNoCacheNoReason, natives=NOT_NATIVES_CODE) at compiler.cc:2806:27
2803 MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
2804 solate* isolate, Handle<String> source,
2805 ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag natives) {
-> 2806 ScriptCompileTimerScope compile_timer(isolate, no_cache_reason);
2807
2808 if (compile_options == ScriptCompiler::kNoCompileOptions ||
2809 compile_options == ScriptCompiler::kEagerCompile) {
Target 0: (d8) stopped.
(lldb) p source
(v8::internal::Handle<v8::internal::String>) $9 = {
v8::internal::HandleBase = {
location_ = 0x000000010f009a60
}
}
(lldb) p *$9
(v8::internal::String) $10 = {
v8::internal::TorqueGeneratedString<v8::internal::String, v8::internal::Name> = {
.....
}
}
Take a look at tools/lldb_commands.py. In short: configure your LLDB to load that script:
echo "command script import /path/to/v8/tools/lldb_commands.py" >> ~/.lldbinit
and then use the convenience commands it provides, the most important one being job, a mnemonic for "JavaScript object". It needs the raw pointer value that you'll see as ptr_ = ... somewhere in the output of p *$9, but you don't need to retrieve it manually. Example:
(lldb) job source->ptr_
0x28c008109019: [String]: "console.log('hello world');"
(Side note: tools/gdbinit tends to have a few more features than tools/lldbinit, because most folks on the team use GDB. We'd be happy to accept patches to improve LLDB support; relevant to the case at hand would be gdbinit's jh shortcut (allowing simply jh source) that currently has no equivalent in lldbinit.)
Related
I have a problem debugging an stm32f407vet6 board and rust code.
The point of the problem is that GDB ignores breakpoints.
After setting breakpoints and executing the "continue" command in gdb, the program continues to ignore all breakpoints.
The only way to stop the program running is to cause an interrupt using the "ctrl + c" command.
After this command, the board stops its execution on the line currently being executed.
I have tried to set breakpoints on all lines where I can set them, but all the attempts are unsuccessful.
$ openocd
Open On-Chip Debugger 0.10.0 (2020-07-01) [https://github.com/sysprogs/openocd]
Licensed under GNU GPL v2
libusb1 09e75e98b4d9ea7909e8837b7a3f00dda4589dc3
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 2000 kHz
Error: libusb_open() failed with LIBUSB_ERROR_NOT_SUPPORTED
Info : STLINK V2J35S7 (API v2) VID:PID 0483:3748
Info : Target voltage: 6.436364
Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f4x.cpu on 3333
Info : Listening on port 3333 for gdb connections
$ arm-none-eabi-gdb -q target\thumbv7em-none-eabihf\debug\test_blink
Reading symbols from target\thumbv7em-none-eabihf\debug\test_blink...
(gdb) target remote :3333
Remote debugging using :3333
0x00004070 in core::ptr::read_volatile (src=0xe000e010) at C:\Users\User\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\src/libcore/ptr/mod.rs:1005
1005 pub unsafe fn read_volatile<T>(src: *const T) -> T {
(gdb) load
Loading section .vector_table, size 0x1a8 lma 0x0
Loading section .text, size 0x47bc lma 0x1a8
Loading section .rodata, size 0xbf0 lma 0x4970
Start address 0x47a2, load size 21844
Transfer rate: 100 KB/sec, 5461 bytes/write.
(gdb) b main
Breakpoint 1 at 0x1f2: file src\main.rs, line 15.
(gdb) continue
Continuing.
Program received signal SIGINT, Interrupt.
0x00001530 in cortex_m::peripheral::syst::<impl cortex_m::peripheral::SYST>::has_wrapped (self=0x1000fc6c)
at C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\cortex-m-0.6.3\src\peripheral/syst.rs:135
135 pub fn has_wrapped(&mut self) -> bool {
(gdb) bt
#0 0x00001530 in cortex_m::peripheral::syst::<impl cortex_m::peripheral::SYST>::has_wrapped (self=0x1000fc6c)
at C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\cortex-m-0.6.3\src\peripheral/syst.rs:135
#1 0x00003450 in <stm32f4xx_hal::delay::Delay as embedded_hal::blocking::delay::DelayUs<u32>>::delay_us (self=0x1000fc6c, us=500000)
at C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\stm32f4xx-hal-0.8.3\src/delay.rs:69
#2 0x0000339e in <stm32f4xx_hal::delay::Delay as embedded_hal::blocking::delay::DelayMs<u32>>::delay_ms (self=0x1000fc6c, ms=500)
at C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\stm32f4xx-hal-0.8.3\src/delay.rs:32
#3 0x00000318 in test_blink::__cortex_m_rt_main () at src\main.rs:40
#4 0x000001f6 in main () at src\main.rs:15
memory.x file:
MEMORY
{
/* NOTE 1 K = 1 KiBi = 1024 bytes */
/* TODO Adjust these memory regions to match your device memory layout */
/* These values correspond to the LM3S6965, one of the few devices QEMU can emulate */
CCMRAM : ORIGIN = 0x10000000, LENGTH = 64K
RAM : ORIGIN = 0x20000000, LENGTH = 128K
FLASH : ORIGIN = 0x00000000, LENGTH = 512K
}
/* This is where the call stack will be allocated. */
/* The stack is of the full descending type. */
/* You may want to use this variable to locate the call stack and static
variables in different memory regions. Below is shown the default value */
_stack_start = ORIGIN(CCMRAM) + LENGTH(CCMRAM);
/* You can use this symbol to customize the location of the .text section */
/* If omitted the .text section will be placed right after the .vector_table
section */
/* This is required only on microcontrollers that store some configuration right
after the vector table */
/* _stext = ORIGIN(FLASH) + 0x400; */
/* Example of putting non-initialized variables into custom RAM locations. */
/* This assumes you have defined a region RAM2 above, and in the Rust
sources added the attribute `#[link_section = ".ram2bss"]` to the data
you want to place there. */
/* Note that the section will not be zero-initialized by the runtime! */
/* SECTIONS {
.ram2bss (NOLOAD) : ALIGN(4) {
*(.ram2bss);
. = ALIGN(4);
} > RAM2
} INSERT AFTER .bss;
*/
openocd.cfg file:
# Sample OpenOCD configuration for the STM32F3DISCOVERY development board
# Depending on the hardware revision you got you'll have to pick ONE of these
# interfaces. At any time only one interface should be commented out.
# Revision C (newer revision)
source [find interface/stlink.cfg]
# Revision A and B (older revisions)
# source [find interface/stlink-v2.cfg]
source [find target/stm32f4x.cfg]
# use hardware reset, connect under reset
# reset_config none separate
main.rs file:
#![no_main]
#![no_std]
#![allow(unsafe_code)]
// Halt on panic
#[allow(unused_extern_crates)] // NOTE(allow) bug rust-lang/rust#53964
extern crate panic_halt; // panic handler
use cortex_m;
use cortex_m_rt::entry;
use stm32f4xx_hal as hal;
use crate::hal::{prelude::*, stm32};
#[entry]
fn main() -> ! {
if let (Some(dp), Some(cp)) = (
stm32::Peripherals::take(),
cortex_m::peripheral::Peripherals::take(),
) {
let rcc = dp.RCC.constrain();
let clocks = rcc
.cfgr
.sysclk(168.mhz())
.freeze();
let mut delay = hal::delay::Delay::new(cp.SYST, clocks);
let gpioa = dp.GPIOA.split();
let mut l1 = gpioa.pa6.into_push_pull_output();
let mut l2 = gpioa.pa7.into_push_pull_output();
loop {
l1.set_low().unwrap();
l2.set_high().unwrap();
delay.delay_ms(500u32);
l1.set_high().unwrap();
l2.set_low().unwrap();
delay.delay_ms(500u32);
}
}
loop {}
}
Cargo.toml file:
[package]
name = "test_blink"
version = "0.1.0"
authors = ["Alex"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
embedded-hal = "0.2"
nb = "0.1.2"
cortex-m = "0.6"
cortex-m-rt = "0.6"
# Panic behaviour, see https://crates.io/keywords/panic-impl for alternatives
panic-halt = "0.2"
cortex-m-log="0.6.2"
[dependencies.stm32f4xx-hal]
version = "0.8.3"
features = ["rt", "stm32f407"]
I am new to rust embedded and maybe I have done something wrong, but I have already tried all the options I can find on the Internet.
At first I thought it was a problem with the cortex-debug plugin for vscode and even created the issue, but the guys couldn't help me because the problem is obviously not on their side.
Debugging "C" code in cubeIDE works, so I dare to assume that the problem is somewhere in rust--gdb--openocd. Perhaps I am missing something, but unfortunately I cannot find it myself yet.
I would appreciate any resources or ideas to solve this problem.
I'm hoping you checked out this resources:
Discovery - debug
From your screen-grab of arm-none-eabi-gdb it does indeed look it it did not hit the break point.
you should have seen this message afterwards:
Note: automatically using hardware breakpoints for read-only addresses.
Breakpoint 1, main () at ...
Did you compile your source with symbols, and unoptimised?
Your config all looks right to me otherwise.
Is there a way, to record the execution of a particular function (or the entire program) in terms of the executed source code lines?
Consdier I set a breakpoint in gdb to function foo, and then repetedly call step, and it will tell me something like this:
(gdb) break foo
Thread 1 "main" hit Breakpoint 1, foo () at foo.cpp:10
(gdb) step
foo () at foo.cpp:12
(gdb) step
foo () at foo.cpp:13
(gdb) step
foo () at foo.cpp:12
(gdb) step
foo () at foo.cpp:14
Then I repeat that until foo is no longer in the output of bt. This gives me a trace of execution (foo.cpp:10->12->13->12->14), that is particularly useful to compare long control flows.
Is there a way to do this with gdb or is there another tool that does this? I am only interested in deterministic traces, not sampling. Ideally this could also be done for stepi (on instruction level) / next (without entering subroutines).
Based on this similar question, I was able to put together a quick python script for my purpose. Fortunately with less required bug-workarounds:
import sys
import gdb
import os
import re
def in_frames(needle):
""" Check if the passed frame is still on the current stack """
hay = gdb.newest_frame()
while hay:
if hay == needle:
return True
hay = hay.older()
return False
# Use this to reduce any kind of unwanted noise
def filter_step(output):
output = re.sub(r'^.*No such file or directory\.\n', r'', output, flags=re.M)
output = re.sub(r'^\d+\s+in\s+.*\n', r'', output, flags=re.M)
return output
def step_trace(filename=None, step="step"):
counter = 0
if filename:
output = ""
frame = gdb.newest_frame()
print("Stepping until end of {} # {}:{}".format(frame.name(), frame.function().symtab, frame.function().line))
while in_frames(frame):
counter += 1
if filename:
output += filter_step(gdb.execute(step, to_string=True))
else:
gdb.execute(step)
if filename:
with open(filename, "w") as file:
file.write(output)
print("Done stepping through {} lines.".format(counter))
To output a trace to a file
(gdb) source step_trace.py
(gdb) python step_trace("filename.log")
or directly
(gdb) source step_trace.py
(gdb) python step_trace()
In Rstudio console, I ran the following commands
> debug(ls)
> ls()
Then, I could not quit/leave the debug mode. I tried the following:
1, "Q" + "enter key"
2, "c" + "enter key"
3. the red "Stop" button.
but it does not leave debug mode.
Browse[2]> Q
debugging in: ls(.Internal(getNamespaceRegistry()), all.names = TRUE)
debug: {
if (!missing(name)) {
Error: unable to quit when browser is active
Browse[2]> c
exiting from: ls(.Internal(getNamespaceRegistry()), all.names = TRUE)
debugging in: ls(.Internal(getNamespaceRegistry()), all.names = TRUE)
debug: {
if (!missing(name)) {
.....
The Rstudio version: Version 0.98.1060 – © 2009-2013 RStudio, Inc.
The R version: R i386.3.1.1
Has anyone had this issue in Rstudio?
Thanks.
Ang
The problem is that as soon as you leave debug mode, something is triggering a call to ls, which puts you back in debug mode. To fix the issue, turn off debugging for ls before you leave the debugger:
Browse[2]> undebug(ls)
Browse[2]> Q
Consider using debugonce rather than debug to avoid getting into these kinds of loops.
Current behavior:
Put a breakpoint on the case Twice(n) ... line.
On "step into" the control goes to x match { line
On "step into" the control goes to def TwiceTest = { line
On further "step into" the control goes to if (z % 2 == 0)... line.
Expected behavior:
Put a breakpoint on the case Twice(n) ... line.
On "step into" the control goes to if (z % 2 == 0)... line.
Code Snippet
object testobj extends App {
def TwiceTest = {
val x = Twice(21)
x match {
case Twice(n) => Console.println(n)
} // prints 21
}
TwiceTest
}
object Twice {
def apply(x: Int): Int = x * 2
def unapply(z: Int): Option[Int] = {
if (z % 2 == 0) Some(z / 2) else None
}
}
The current behavior is irritating while debugging a scala program with lots of nested extractors. I tried this with the new Scala debugger as well as the Java debugger but with the same result.
Step Filtering also does not help in this case.
As a workaround, I am putting a breakpoint in the unapply method and running resume from the first breakpoint. Can someone please suggest me a cleaner method.
Edit 1
I am using Scala-IDE (latest nightly build. 2.1.0.nightly-2_09-201208250315-529cd70 )
Eclipse Version: Indigo Service Release 2 Build id: 20120216-1857
OS: Windows 7 ( 64 bit)
The line number information in the bytecode is wrong. It is not an issue with the IDE, but the Scala compiler. When pattern matching is compiled, synthetic code sometimes gets the wrong position information.
I assume you are using Scala 2.9.2. In the next version of Scala (2.10.0), there are significant improvements in the pattern matcher, so it would be good to give it a try.
I come from a Python background, where at any point in my code I can add
import pdb; pdb.set_trace()
and at runtime I'll be dropped into an interactive interpreter at that spot. Is there an equivalent for scala, or is this not possible at runtime?
Yes, you can, on Scala 2.8. Note that, for this to work, you have to include the scala-compiler.jar in your classpath. If you invoke your scala program with scala, it will be done automatically (or so it seems in the tests I made).
You can then use it like this:
import scala.tools.nsc.Interpreter._
object TestDebugger {
def main(args: Array[String]) {
0 to 10 foreach { i =>
breakIf(i == 5, DebugParam("i", i))
println(i)
}
}
}
You may pass multiple DebugParam arguments. When the REPL comes up, the value on the right will be bound to a val whose name you provided on the left. For instance, if I change that line like this:
breakIf(i == 5, DebugParam("j", i))
Then the execution will happen like this:
C:\Users\Daniel\Documents\Scala\Programas>scala TestDebugger
0
1
2
3
4
j: Int
scala> j
res0: Int = 5
You continue the execution by typing :quit.
You may also unconditionally drop into REPL by invoking break, which receives a List of DebugParam instead of a vararg. Here's a full example, code and execution:
import scala.tools.nsc.Interpreter._
object TestDebugger {
def main(args: Array[String]) {
0 to 10 foreach { i =>
breakIf(i == 5, DebugParam("j", i))
println(i)
if (i == 7) break(Nil)
}
}
}
And then:
C:\Users\Daniel\Documents\Scala\Programas>scalac TestDebugger.scala
C:\Users\Daniel\Documents\Scala\Programas>scala TestDebugger
0
1
2
3
4
j: Int
scala> j
res0: Int = 5
scala> :quit
5
6
7
scala> j
<console>:5: error: not found: value j
j
^
scala> :quit
8
9
10
C:\Users\Daniel\Documents\Scala\Programas>
To add to Daniel's answer, as of Scala 2.9, the break and breakIf methods are contained in scala.tools.nsc.interpreter.ILoop. Also, DebugParam is now NamedParam.
IntelliJ IDEA:
Run in debug mode or attach a remote debugger
Set a breakpoint and run until you reach it
Open Evaluate Expression (Alt+F8, in menu: Run -> Evaluate Expression) window to run arbitrary Scala code.
Type what code fragment or expression you want to run and click on Evaluate
Type Alt+V or click on Evaluate to run the code fragment.
Eclipse:
As of Scala 2.10 both break and breakIf have been removed from ILoop.
To break into interpreter you will have to work with ILoop directly.
First add scala compiler library. For Eclipse Scala, right click on project => Build Path => Add Libraries... => Scala Compiler.
And then you can use the following where you want to start the interpreter:
import scala.tools.nsc.interpreter.ILoop
import scala.tools.nsc.interpreter.SimpleReader
import scala.tools.nsc.Settings
val repl = new ILoop
repl.settings = new Settings
repl.settings.Yreplsync.value = true
repl.in = SimpleReader()
repl.createInterpreter()
// bind any local variables that you want to have access to
repl.intp.bind("row", "Int", row)
repl.intp.bind("col", "Int", col)
// start the interpreter and then close it after you :quit
repl.loop()
repl.closeInterpreter()
In Eclipse Scala the interpreter can be used from the Console view: