Snap for 11406759 from d2cab6364444b0184b9aaa45b62fd65ee824d287 to 24Q2-release

Change-Id: I455049957b84e91c55c5e982b6aa627c0736f17f
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 8350bf5..a01e1c3 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,6 +1,6 @@
 {
   "git": {
-    "sha1": "c489dcdf5992d6e7ebfcf37775ce81dc8cf7861d"
+    "sha1": "927a961339353dca76882863160458cf5f7d0c66"
   },
   "path_in_vcs": ""
 }
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 654cb99..4c21db2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -23,7 +23,7 @@
     host_supported: true,
     crate_name: "gdbstub",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.7.0",
+    cargo_pkg_version: "0.7.1",
     srcs: ["src/lib.rs"],
     edition: "2018",
     features: [
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 97a4ae4..955a65d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,12 @@
 
 This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+# 0.7.1
+
+#### New Protocol Extensions
+
+- `LibrariesSvr4` - List an SVR4 (System-V/Unix) target's libraries. [\#142](https://github.com/daniel5151/gdbstub/pull/142) ([alexcrichton](https://github.com/alexcrichton))
+
 # 0.7.0
 
 #### Breaking API Changes
@@ -14,9 +20,9 @@
   - Entirely removed `single_step_behavior`. See [\#132](https://github.com/daniel5151/gdbstub/pull/132) for details and rationale
 - `Target` APIs:
   - `SingleThreadBase`/`MultiThreadBase`
-    - `read_addrs` now returns a `usize` instead of a `()`, allowing implementations to report cases where only a subset of memory could be read.
+    - `read_addrs` now returns a `usize` instead of a `()`, allowing implementations to report cases where only a subset of memory could be read. [\#115](https://github.com/daniel5151/gdbstub/pull/115) ([geigerzaehler](https://github.com/geigerzaehler))
   - `HostIo`
-    - `bitflags` has been updated from `1.x` to `2.x`, affecting the type of `HostIoOpenFlags` and `HostIoOpenMode`
+    - `bitflags` has been updated from `1.x` to `2.x`, affecting the type of `HostIoOpenFlags` and `HostIoOpenMode` [\#138](https://github.com/daniel5151/gdbstub/pull/138) ([qwandor](https://github.com/qwandor))
 
 #### Internal Improvements
 
diff --git a/Cargo.toml b/Cargo.toml
index 0eb81ed..016d8f3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,7 +12,7 @@
 [package]
 edition = "2018"
 name = "gdbstub"
-version = "0.7.0"
+version = "0.7.1"
 authors = ["Daniel Prilik <[email protected]>"]
 exclude = [
     "examples/**/*.elf",
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 445e67b..c9e7129 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -2,7 +2,7 @@
 name = "gdbstub"
 description = "An implementation of the GDB Remote Serial Protocol in Rust"
 authors = ["Daniel Prilik <[email protected]>"]
-version = "0.7.0"
+version = "0.7.1"
 license = "MIT OR Apache-2.0"
 edition = "2018"
 readme = "README.md"
diff --git a/METADATA b/METADATA
index 146415c..5cfadfe 100644
--- a/METADATA
+++ b/METADATA
@@ -1,5 +1,5 @@
 # This project was upgraded with external_updater.
-# Usage: tools/external_updater/updater.sh update rust/crates/gdbstub
+# Usage: tools/external_updater/updater.sh update external/rust/crates/gdbstub
 # For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
 
 name: "gdbstub"
@@ -7,14 +7,14 @@
 third_party {
   license_type: NOTICE
   last_upgrade_date {
-    year: 2023
-    month: 12
-    day: 16
+    year: 2024
+    month: 2
+    day: 1
   }
   homepage: "https://crates.io/crates/gdbstub"
   identifier {
     type: "Archive"
-    value: "https://static.crates.io/crates/gdbstub/gdbstub-0.7.0.crate"
-    version: "0.7.0"
+    value: "https://static.crates.io/crates/gdbstub/gdbstub-0.7.1.crate"
+    version: "0.7.1"
   }
 }
diff --git a/README.md b/README.md
index 4ce94e4..8d48585 100644
--- a/README.md
+++ b/README.md
@@ -88,6 +88,7 @@
     -   Can be used to automatically read the remote executable on attach (using `ExecFile`)
 -   Read auxiliary vector (`info auxv`)
 -   Extra thread info (`info threads`)
+-   Extra library information (`info sharedlibraries`)
 
 _Note:_ GDB features are implemented on an as-needed basis by `gdbstub`'s contributors. If there's a missing GDB feature that you'd like `gdbstub` to implement, please file an issue and/or open a PR!
 
diff --git a/examples/armv4t/gdb/libraries.rs b/examples/armv4t/gdb/libraries.rs
new file mode 100644
index 0000000..0c64dd7
--- /dev/null
+++ b/examples/armv4t/gdb/libraries.rs
@@ -0,0 +1,28 @@
+use super::copy_range_to_buf;
+use crate::emu::Emu;
+use gdbstub::target;
+use gdbstub::target::TargetResult;
+
+impl target::ext::libraries::LibrariesSvr4 for Emu {
+    fn get_libraries_svr4(
+        &self,
+        offset: u64,
+        length: usize,
+        buf: &mut [u8],
+    ) -> TargetResult<usize, Self> {
+        // `l_ld` is the address of the `PT_DYNAMIC` ELF segment, so fake an
+        // address here.
+        //
+        // The `main-lm`, `lm`, and `lmid` seem to refer to in-memory structures
+        // which gdb may read, but gdb also seems to work well enough if they're
+        // null-ish or otherwise pointing to non-present things.
+        let xml = r#"
+<library-list-svr4 version="1.0" main-lm="0x4">
+    <library name="/test.elf" lm="0x8" l_addr="0" l_ld="0" lmid="0x14"/>
+</library-list-svr4>
+"#
+        .trim()
+        .as_bytes();
+        Ok(copy_range_to_buf(xml, offset, length, buf))
+    }
+}
diff --git a/examples/armv4t/gdb/mod.rs b/examples/armv4t/gdb/mod.rs
index 5837ddd..b56ce9a 100644
--- a/examples/armv4t/gdb/mod.rs
+++ b/examples/armv4t/gdb/mod.rs
@@ -20,6 +20,7 @@
 mod exec_file;
 mod extended_mode;
 mod host_io;
+mod libraries;
 mod lldb_register_info_override;
 mod memory_map;
 mod monitor_cmd;
@@ -153,6 +154,13 @@
     fn support_auxv(&mut self) -> Option<target::ext::auxv::AuxvOps<'_, Self>> {
         Some(self)
     }
+
+    #[inline(always)]
+    fn support_libraries_svr4(
+        &mut self,
+    ) -> Option<target::ext::libraries::LibrariesSvr4Ops<'_, Self>> {
+        Some(self)
+    }
 }
 
 impl SingleThreadBase for Emu {
diff --git a/src/protocol/commands.rs b/src/protocol/commands.rs
index 1229899..115e76b 100644
--- a/src/protocol/commands.rs
+++ b/src/protocol/commands.rs
@@ -330,4 +330,8 @@
     lldb_register_info {
         "qRegisterInfo" => _qRegisterInfo::qRegisterInfo,
     }
+
+    libraries_svr4 use 'a {
+        "qXfer:libraries-svr4:read" => _qXfer_libraries_svr4_read::qXferLibrariesSvr4Read<'a>,
+    }
 }
diff --git a/src/protocol/commands/_qXfer_libraries_svr4_read.rs b/src/protocol/commands/_qXfer_libraries_svr4_read.rs
new file mode 100644
index 0000000..be050f4
--- /dev/null
+++ b/src/protocol/commands/_qXfer_libraries_svr4_read.rs
@@ -0,0 +1,18 @@
+use crate::protocol::common::qxfer::ParseAnnex;
+use crate::protocol::common::qxfer::QXferReadBase;
+
+pub type qXferLibrariesSvr4Read<'a> = QXferReadBase<'a, LibrariesSvr4Annex>;
+
+#[derive(Debug)]
+pub struct LibrariesSvr4Annex;
+
+impl<'a> ParseAnnex<'a> for LibrariesSvr4Annex {
+    #[inline(always)]
+    fn from_buf(buf: &[u8]) -> Option<Self> {
+        if buf != b"" {
+            return None;
+        }
+
+        Some(LibrariesSvr4Annex)
+    }
+}
diff --git a/src/stub/core_impl.rs b/src/stub/core_impl.rs
index 07774d4..2ea3bc8 100644
--- a/src/stub/core_impl.rs
+++ b/src/stub/core_impl.rs
@@ -31,6 +31,7 @@
 mod exec_file;
 mod extended_mode;
 mod host_io;
+mod libraries;
 mod lldb_register_info;
 mod memory_map;
 mod monitor_cmd;
@@ -216,6 +217,7 @@
             Command::Auxv(cmd) => self.handle_auxv(res, target, cmd),
             Command::ThreadExtraInfo(cmd) => self.handle_thread_extra_info(res, target, cmd),
             Command::LldbRegisterInfo(cmd) => self.handle_lldb_register_info(res, target, cmd),
+            Command::LibrariesSvr4(cmd) => self.handle_libraries_svr4(res, target, cmd),
             // in the worst case, the command could not be parsed...
             Command::Unknown(cmd) => {
                 // HACK: if the user accidentally sends a resume command to a
diff --git a/src/stub/core_impl/base.rs b/src/stub/core_impl/base.rs
index 9110297..eebb715 100644
--- a/src/stub/core_impl/base.rs
+++ b/src/stub/core_impl/base.rs
@@ -195,6 +195,10 @@
                     res.write_str(";qXfer:auxv:read+")?;
                 }
 
+                if target.support_libraries_svr4().is_some() {
+                    res.write_str(";qXfer:libraries-svr4:read+")?;
+                }
+
                 HandlerStatus::Handled
             }
 
diff --git a/src/stub/core_impl/libraries.rs b/src/stub/core_impl/libraries.rs
new file mode 100644
index 0000000..dd18cb7
--- /dev/null
+++ b/src/stub/core_impl/libraries.rs
@@ -0,0 +1,36 @@
+use super::prelude::*;
+use crate::protocol::commands::ext::LibrariesSvr4;
+
+impl<T: Target, C: Connection> GdbStubImpl<T, C> {
+    pub(crate) fn handle_libraries_svr4(
+        &mut self,
+        res: &mut ResponseWriter<'_, C>,
+        target: &mut T,
+        command: LibrariesSvr4<'_>,
+    ) -> Result<HandlerStatus, Error<T::Error, C::Error>> {
+        let ops = match target.support_libraries_svr4() {
+            Some(ops) => ops,
+            None => return Ok(HandlerStatus::Handled),
+        };
+
+        crate::__dead_code_marker!("libraries-svr4", "impl");
+
+        let handler_status = match command {
+            LibrariesSvr4::qXferLibrariesSvr4Read(cmd) => {
+                let ret = ops
+                    .get_libraries_svr4(cmd.offset, cmd.length, cmd.buf)
+                    .handle_error()?;
+                if ret == 0 {
+                    res.write_str("l")?;
+                } else {
+                    res.write_str("m")?;
+                    // TODO: add more specific error variant?
+                    res.write_binary(cmd.buf.get(..ret).ok_or(Error::PacketBufferOverflow)?)?;
+                }
+                HandlerStatus::Handled
+            }
+        };
+
+        Ok(handler_status)
+    }
+}
diff --git a/src/target/ext/libraries.rs b/src/target/ext/libraries.rs
new file mode 100644
index 0000000..5feea82
--- /dev/null
+++ b/src/target/ext/libraries.rs
@@ -0,0 +1,29 @@
+//! Report information about the loaded shared libraries for targets where there
+//! are possibly multiple files to be debugged mapped into the same address
+//! space.
+
+use crate::target::Target;
+use crate::target::TargetResult;
+
+/// Target Extension - List an SVR4 (System-V/Unix) target's libraries.
+pub trait LibrariesSvr4: Target {
+    /// Get library list XML for this target.
+    ///
+    /// See the [GDB Documentation] for a description of the format.
+    ///
+    /// [GDB Documentation]: https://sourceware.org/gdb/current/onlinedocs/gdb.html/Library-List-Format-for-SVR4-Targets.html
+    ///
+    /// Return the number of bytes written into `buf` (which may be less than
+    /// `length`).
+    ///
+    /// If `offset` is greater than the length of the underlying data, return
+    /// `Ok(0)`.
+    fn get_libraries_svr4(
+        &self,
+        offset: u64,
+        length: usize,
+        buf: &mut [u8],
+    ) -> TargetResult<usize, Self>;
+}
+
+define_ext!(LibrariesSvr4Ops, LibrariesSvr4);
diff --git a/src/target/ext/mod.rs b/src/target/ext/mod.rs
index b7e2d8f..a6f3d95 100644
--- a/src/target/ext/mod.rs
+++ b/src/target/ext/mod.rs
@@ -265,6 +265,7 @@
 pub mod exec_file;
 pub mod extended_mode;
 pub mod host_io;
+pub mod libraries;
 pub mod lldb_register_info_override;
 pub mod memory_map;
 pub mod monitor_cmd;
diff --git a/src/target/ext/section_offsets.rs b/src/target/ext/section_offsets.rs
index eb80578..e778018 100644
--- a/src/target/ext/section_offsets.rs
+++ b/src/target/ext/section_offsets.rs
@@ -8,6 +8,13 @@
 //! limited to reporting the offsets for code, data and bss, and is
 //! generally considered a legacy feature.
 //!
+//! For System-V architectures GDB may use the `qXfer:libraries-svr4:read`
+//! command to try to learn about loaded libraries and this can be implemented
+//! with the [`LibrariesSvr4`
+//! trait](crate::target::ext::libraries::LibrariesSvr4). Note that not all
+//! targets may query this and it may not be applicable in all situations
+//! either.
+//!
 //! For targets where library offsets are maintained externally (e.g. Windows)
 //! you should consider implementing the more flexible `qXfer:library:read`.
 //! See issue [#20](https://github.com/daniel5151/gdbstub/issues/20) for more
diff --git a/src/target/mod.rs b/src/target/mod.rs
index 2b00d0b..da9541c 100644
--- a/src/target/mod.rs
+++ b/src/target/mod.rs
@@ -676,6 +676,13 @@
     fn support_auxv(&mut self) -> Option<ext::auxv::AuxvOps<'_, Self>> {
         None
     }
+
+    /// Support for reading a list of libraries for SVR4 (System-V/Unix)
+    /// platforms.
+    #[inline(always)]
+    fn support_libraries_svr4(&mut self) -> Option<ext::libraries::LibrariesSvr4Ops<'_, Self>> {
+        None
+    }
 }
 
 macro_rules! __delegate {