Repository: rizinorg/rizin
Pull request #5056: A command to show just strings that have code or data references to them
Author: login: ahmed-kamal2004
Labels: name: rz-test
name: API
name: RzCore
Created: 2025-04-01T14:56:32Z | Merged: 2025-04-21T06:43:01Z

 <!-- Filling this template is mandatory -->

**Your checklist for this pull request**
- [x] I've read the [guidelines for contributing](https://github.com/rizinorg/rizin/blob/master/DEVELOPERS.md) to this repository.
- [x] I made sure to follow the project's [coding style](https://github.com/rizinorg/rizin/blob/master/DEVELOPERS.md#code-style).
- [ ] I've documented every `RZ_API` function and struct this PR changes.
- [x] I've added tests that prove my changes are effective (required for changes to `RZ_API`).
- [ ] I've updated the [Rizin book](https://github.com/rizinorg/book) with the relevant information (if needed).

**Detailed description**
This PR solves issue #4702
Add new command `izx` responsible for fetching strings with data or code xrefs to them.
...

**Test plan**

Command `izx` using

![Screenshot from 2025-04-01 16-21-21](https://github.com/user-attachments/assets/373bb6a9-0c03-42c2-97ad-fa2718031f85)

`izxj` `izxq` `izxQ` `izxt`

![Screenshot from 2025-04-01 16-54-11](https://github.com/user-attachments/assets/6ebe0d7c-6944-4136-9169-bd48c6c769b0)

Complete view

![Screenshot from 2025-04-01 16-21-55](https://github.com/user-attachments/assets/55755417-4e22-46ad-9039-539a758f23e2)


...

**Closing issues**

<!-- put "closes #XXXX" in your comment to auto-close the issue that your PR fixes (if any). -->
closes #4702 

...


Linked issue #4702: A command to show just strings that have code or data references to them
Currently there is no dedicated command to show just strings that have XREFs to them, from either code or data (separation by these two categories could be done as subcommands also). But the task itself is quite common.

For both `iz` and `/` commands.

Linked issue comments: user: login: ahmed-kamal2004
created_at: 2025-03-29T14:30:39Z
body: will work on this
author_association: MEMBER

Diff:
diff --git a/librz/core/cbin.c b/librz/core/cbin.c
index 9e3dc9f4776..035e8400c63 100644
--- a/librz/core/cbin.c
+++ b/librz/core/cbin.c
@@ -2946,6 +2946,47 @@ RZ_API bool rz_core_bin_whole_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL
 	return res;
 }
 
+RZ_API bool rz_core_bin_xrefs_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state) {
+	rz_return_val_if_fail(core && state, false);
+
+	RzPVector *whole_strings = rz_core_bin_whole_strings(core, bf);
+
+	if (!whole_strings) {
+		return false;
+	}
+
+	RzPVector *xrefs_strings = rz_pvector_new((RzPVectorFree)rz_bin_string_free);
+
+	if (!xrefs_strings) {
+		rz_pvector_free(whole_strings);
+		return false;
+	}
+
+	void **iter;
+	rz_pvector_foreach (whole_strings, iter) {
+		RzBinString *string = *iter;
+		const RzList *list = rz_analysis_xrefs_get_to(core->analysis, string->paddr);
+		const RzAnalysisXRef *xref;
+		const RzListIter *iterator;
+		rz_list_foreach (list, iterator, xref) {
+			switch (xref->type) {
+			case RZ_ANALYSIS_XREF_TYPE_CODE:
+			case RZ_ANALYSIS_XREF_TYPE_DATA:
+				if (!rz_pvector_contains(xrefs_strings, string)) {
+					rz_pvector_remove_data(whole_strings, string);
+					rz_pvector_push_front(xrefs_strings, string);
+				}
+			default:
+				break;
+			}
+		}
+	}
+	bool res = strings_print(core, state, xrefs_strings);
+	rz_pvector_free(whole_strings);
+	rz_pvector_free(xrefs_strings);
+	return res;
+}
+
 static const char *get_filename(RzBinInfo *info, RzIODesc *desc) {
 	if (info && info->file) {
 		return info->file;
diff --git a/librz/core/cmd/cmd_info.c b/librz/core/cmd/cmd_info.c
index 6ce43167b9d..09b85e7346f 100644
--- a/librz/core/cmd/cmd_info.c
+++ b/librz/core/cmd/cmd_info.c
@@ -709,3 +709,8 @@ RZ_IPI RzCmdStatus rz_cmd_info_guess_size_handler(RzCore *core, int argc, const
 	}
 	return bool2status(res);
 }
+
+RZ_IPI RzCmdStatus rz_cmd_info_xrefs_strings_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state) {
+	RzBinFile *bf = rz_bin_cur(core->bin);
+	return bool2status(rz_core_bin_xrefs_strings_print(core, bf, state));
+}
\ No newline at end of file
diff --git a/librz/core/cmd_descs/cmd_descs.c b/librz/core/cmd_descs/cmd_descs.c
index 80b24475b37..95f5b4ef0ca 100644
--- a/librz/core/cmd_descs/cmd_descs.c
+++ b/librz/core/cmd_descs/cmd_descs.c
@@ -13173,6 +13173,14 @@ static const RzCmdDescHelp cmd_info_guess_size_help = {
 	.args = cmd_info_guess_size_args,
 };
 
+static const RzCmdDescArg cmd_info_xrefs_strings_args[] = {
+	{ 0 },
+};
+static const RzCmdDescHelp cmd_info_xrefs_strings_help = {
+	.summary = "List all strings which have xrefs to them.",
+	.args = cmd_info_xrefs_strings_args,
+};
+
 static const RzCmdDescHelp k_help = {
 	.summary = "Run query (SDB)",
 };
@@ -23542,6 +23550,10 @@ RZ_IPI void rzshell_cmddescs_init(RzCore *core) {
 	RzCmdDesc *cmd_info_guess_size_cd = rz_cmd_desc_argv_state_new(core->rcmd, i_cd, "iZ", RZ_OUTPUT_MODE_JSON | RZ_OUTPUT_MODE_STANDARD | RZ_OUTPUT_MODE_RIZIN, rz_cmd_info_guess_size_handler, &cmd_info_guess_size_help);
 	rz_warn_if_fail(cmd_info_guess_size_cd);
 
+	RzCmdDesc *cmd_info_xrefs_strings_cd = rz_cmd_desc_argv_state_new(core->rcmd, i_cd, "izx", RZ_OUTPUT_MODE_TABLE | RZ_OUTPUT_MODE_JSON | RZ_OUTPUT_MODE_QUIET | RZ_OUTPUT_MODE_QUIETEST, rz_cmd_info_xrefs_strings_handler, &cmd_info_xrefs_strings_help);
+	rz_warn_if_fail(cmd_info_xrefs_strings_cd);
+	rz_cmd_desc_set_default_mode(cmd_info_xrefs_strings_cd, RZ_OUTPUT_MODE_TABLE);
+
 	RzCmdDesc *k_cd = rz_cmd_desc_group_new(core->rcmd, root_cd, "k", rz_query_sdb_get_set_handler, &query_sdb_get_set_help, &k_help);
 	rz_warn_if_fail(k_cd);
 	RzCmdDesc *query_dump_json_cd = rz_cmd_desc_argv_new(core->rcmd, k_cd, "kj", rz_query_dump_json_handler, &query_dump_json_help);
diff --git a/librz/core/cmd_descs/cmd_descs.h b/librz/core/cmd_descs/cmd_descs.h
index 2ecc28d89c4..16c43892724 100644
--- a/librz/core/cmd_descs/cmd_descs.h
+++ b/librz/core/cmd_descs/cmd_descs.h
@@ -1732,6 +1732,8 @@ RZ_IPI RzCmdStatus rz_cmd_info_whole_strings_handler(RzCore *core, int argc, con
 RZ_IPI RzCmdStatus rz_cmd_info_purge_string_handler(RzCore *core, int argc, const char **argv);
 // "iZ"
 RZ_IPI RzCmdStatus rz_cmd_info_guess_size_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state);
+// "izx"
+RZ_IPI RzCmdStatus rz_cmd_info_xrefs_strings_handler(RzCore *core, int argc, const char **argv, RzCmdStateOutput *state);
 // "k"
 RZ_IPI RzCmdStatus rz_query_sdb_get_set_handler(RzCore *core, int argc, const char **argv);
 // "kj"
diff --git a/librz/core/cmd_descs/cmd_info.yaml b/librz/core/cmd_descs/cmd_info.yaml
index ae6ca7037c3..4ed623e8357 100644
--- a/librz/core/cmd_descs/cmd_info.yaml
+++ b/librz/core/cmd_descs/cmd_info.yaml
@@ -489,3 +489,14 @@ commands:
       - RZ_OUTPUT_MODE_STANDARD
       - RZ_OUTPUT_MODE_RIZIN
     args: []
+  - name: izx
+    cname: cmd_info_xrefs_strings
+    summary: List all strings which have xrefs to them.
+    type: RZ_CMD_DESC_TYPE_ARGV_STATE
+    default_mode: RZ_OUTPUT_MODE_TABLE
+    modes:
+      - RZ_OUTPUT_MODE_TABLE
+      - RZ_OUTPUT_MODE_JSON
+      - RZ_OUTPUT_MODE_QUIET
+      - RZ_OUTPUT_MODE_QUIETEST
+    args: []
diff --git a/librz/include/rz_core.h b/librz/include/rz_core.h
index 728823bcccf..2e98df5245b 100644
--- a/librz/include/rz_core.h
+++ b/librz/include/rz_core.h
@@ -1014,6 +1014,7 @@ RZ_API bool rz_core_bin_segments_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBin
 RZ_API bool rz_core_bin_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state);
 RZ_API RZ_OWN RzPVector /*<RzBinString *>*/ *rz_core_bin_whole_strings(RZ_NONNULL RzCore *core, RZ_NULLABLE RzBinFile *bf);
 RZ_API bool rz_core_bin_whole_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state);
+RZ_API bool rz_core_bin_xrefs_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state);
 RZ_API bool rz_core_file_info_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state);
 RZ_API bool rz_core_bin_info_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state);
 RZ_API bool rz_core_bin_classes_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state);
diff --git a/test/db/cmd/cmd_i b/test/db/cmd/cmd_i
index b3b9457208c..0d3a3a1772b 100644
--- a/test/db/cmd/cmd_i
+++ b/test/db/cmd/cmd_i
@@ -4648,6 +4648,15 @@ EXPECT=<<EOF
 EOF
 RUN
 
+NAME=izx
+FILE=bins/arm/elf/hello_world 
+CMDS=aaa;izxq
+EXPECT=<<EOF
+0x574 13 12 Hello world!
+0x494 11 10 \bH\tKxD\tJ{D
+EOF
+RUN
+
 NAME=iT
 FILE==
 ARGS=-w


Reviews:
user: login: Rot127
body: Please add a test in `test/db/cmd/cmd_i`.
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-04-01T15:07:31Z
user: login: ahmed-kamal2004
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-01T15:09:43Z
user: login: ahmed-kamal2004
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-01T15:12:12Z
user: login: ahmed-kamal2004
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-01T15:13:06Z
user: login: Rot127
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-01T15:19:35Z
user: login: wargio
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-16T12:51:48Z
user: login: wargio
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-17T09:59:59Z
user: login: ahmed-kamal2004
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-17T10:32:42Z
user: login: ahmed-kamal2004
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-18T09:14:34Z
user: login: wargio
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-18T11:03:34Z
user: login: ahmed-kamal2004
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-18T11:28:37Z
user: login: wargio
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-18T16:04:35Z
user: login: ahmed-kamal2004
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-18T16:31:56Z
user: login: wargio
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-19T10:43:09Z
user: login: wargio
body: LGTM. @notxvilka can you give a look?
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-19T16:09:15Z
user: login: notxvilka
body: Ideally, we should have an API function that returns `RzList` (or even better,  `RzPVector`) of such strings, and the print function only uses this. But it could be done in a separate PR as well.
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-20T07:01:02Z

Review comments:
diff_hunk: @@ -489,3 +489,14 @@ commands:
       - RZ_OUTPUT_MODE_STANDARD
       - RZ_OUTPUT_MODE_RIZIN
     args: []
+  - name: izx
+    cname: cmd_info_xrefs_strings
+    summary: List strings in the whole binary with xrefs pointing to it.
path: librz/core/cmd_descs/cmd_info.yaml
user: login: Rot127
body: ```suggestion
    summary: List all strings which have xrefs to them.
```
created_at: 2025-04-01T15:00:20Z
author_association: MEMBER
diff_hunk: @@ -25,14 +25,14 @@
 
 #define LOAD_BSS_MALLOC 0
 
-#define IS_MODE_SET(mode)       ((mode)&RZ_MODE_SET)
-#define IS_MODE_SIMPLE(mode)    ((mode)&RZ_MODE_SIMPLE)
-#define IS_MODE_SIMPLEST(mode)  ((mode)&RZ_MODE_SIMPLEST)
-#define IS_MODE_JSON(mode)      ((mode)&RZ_MODE_JSON)
-#define IS_MODE_RZCMD(mode)     ((mode)&RZ_MODE_RIZINCMD)
-#define IS_MODE_EQUAL(mode)     ((mode)&RZ_MODE_EQUAL)
+#define IS_MODE_SET(mode)       ((mode) & RZ_MODE_SET)
+#define IS_MODE_SIMPLE(mode)    ((mode) & RZ_MODE_SIMPLE)
+#define IS_MODE_SIMPLEST(mode)  ((mode) & RZ_MODE_SIMPLEST)
+#define IS_MODE_JSON(mode)      ((mode) & RZ_MODE_JSON)
+#define IS_MODE_RZCMD(mode)     ((mode) & RZ_MODE_RIZINCMD)
+#define IS_MODE_EQUAL(mode)     ((mode) & RZ_MODE_EQUAL)
 #define IS_MODE_NORMAL(mode)    (!(mode))
-#define IS_MODE_CLASSDUMP(mode) ((mode)&RZ_MODE_CLASSDUMP)
+#define IS_MODE_CLASSDUMP(mode) ((mode) & RZ_MODE_CLASSDUMP)
path: librz/core/cbin.c
user: login: Rot127
body: Please use `clang-format-16` for formatting.
created_at: 2025-04-01T15:01:24Z
author_association: MEMBER
diff_hunk: @@ -2946,6 +2946,36 @@ RZ_API bool rz_core_bin_whole_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL
 	return res;
 }
 
+RZ_IPI bool rz_core_bin_xrefs_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state) {
+	rz_return_val_if_fail(core && state, false);
+
+	RzPVector *l = rz_core_bin_whole_strings(core, bf);
+	RzPVector *ll = rz_pvector_new(NULL);
path: librz/core/cbin.c
user: login: Rot127
body: Please rename `ll` and `l` to something more descriptive. It is important to get into the habit of naming variables properly.
created_at: 2025-04-01T15:02:28Z
author_association: MEMBER
diff_hunk: @@ -2946,6 +2946,36 @@ RZ_API bool rz_core_bin_whole_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL
 	return res;
 }
 
+RZ_IPI bool rz_core_bin_xrefs_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state) {
+	rz_return_val_if_fail(core && state, false);
+
+	RzPVector *l = rz_core_bin_whole_strings(core, bf);
+	RzPVector *ll = rz_pvector_new(NULL);
+
+	void **iter;
+	rz_pvector_foreach (l, iter) {
+		RzBinString *string = *iter;
+		RzList *list = rz_analysis_xrefs_get_to(core->analysis, string->paddr);
path: librz/core/cbin.c
user: login: Rot127
body: ```suggestion
		const RzList *list = rz_analysis_xrefs_get_to(core->analysis, string->paddr);
```
created_at: 2025-04-01T15:03:31Z
author_association: MEMBER
diff_hunk: @@ -2946,6 +2946,36 @@ RZ_API bool rz_core_bin_whole_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL
 	return res;
 }
 
+RZ_IPI bool rz_core_bin_xrefs_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state) {
+	rz_return_val_if_fail(core && state, false);
+
+	RzPVector *l = rz_core_bin_whole_strings(core, bf);
+	RzPVector *ll = rz_pvector_new(NULL);
path: librz/core/cbin.c
user: login: Rot127
body: Also, the new pvector needs the free function for `RzBinString` passed. Otherwise we get leaks.
created_at: 2025-04-01T15:06:03Z
author_association: MEMBER
diff_hunk: @@ -2946,6 +2946,36 @@ RZ_API bool rz_core_bin_whole_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL
 	return res;
 }
 
+RZ_IPI bool rz_core_bin_xrefs_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state) {
+	rz_return_val_if_fail(core && state, false);
+
+	RzPVector *l = rz_core_bin_whole_strings(core, bf);
+	RzPVector *ll = rz_pvector_new(NULL);
+
+	void **iter;
+	rz_pvector_foreach (l, iter) {
+		RzBinString *string = *iter;
+		RzList *list = rz_analysis_xrefs_get_to(core->analysis, string->paddr);
+		RzAnalysisXRef *xref;
+		RzListIter *iterator;
+		rz_list_foreach (list, iterator, xref) {
+			switch (xref->type) {
+			case RZ_ANALYSIS_XREF_TYPE_CODE:
+			case RZ_ANALYSIS_XREF_TYPE_DATA:
+				if (!rz_pvector_contains(ll, string)) {
+					rz_pvector_push_front(ll, string);
path: librz/core/cbin.c
user: login: Rot127
body: The string needs to be `popped` from the other list, otherwise there are two owners and you get a double free.
created_at: 2025-04-01T15:07:26Z
author_association: MEMBER
diff_hunk: @@ -2946,6 +2946,36 @@ RZ_API bool rz_core_bin_whole_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL
 	return res;
 }
 
+RZ_IPI bool rz_core_bin_xrefs_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state) {
+	rz_return_val_if_fail(core && state, false);
+
+	RzPVector *l = rz_core_bin_whole_strings(core, bf);
+	RzPVector *ll = rz_pvector_new(NULL);
path: librz/core/cbin.c
user: login: ahmed-kamal2004
body: regarding the new `pvector` actually I tried to make it as you said but some errors found, but with the new info that it may cause leaks, I will find a way to solve that.
created_at: 2025-04-01T15:09:43Z
author_association: MEMBER
diff_hunk: @@ -2946,6 +2946,36 @@ RZ_API bool rz_core_bin_whole_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL
 	return res;
 }
 
+RZ_IPI bool rz_core_bin_xrefs_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state) {
+	rz_return_val_if_fail(core && state, false);
+
+	RzPVector *l = rz_core_bin_whole_strings(core, bf);
+	RzPVector *ll = rz_pvector_new(NULL);
+
+	void **iter;
+	rz_pvector_foreach (l, iter) {
+		RzBinString *string = *iter;
+		RzList *list = rz_analysis_xrefs_get_to(core->analysis, string->paddr);
path: librz/core/cbin.c
user: login: ahmed-kamal2004
body: ok, thanks
created_at: 2025-04-01T15:12:11Z
author_association: MEMBER
diff_hunk: @@ -2946,6 +2946,36 @@ RZ_API bool rz_core_bin_whole_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL
 	return res;
 }
 
+RZ_IPI bool rz_core_bin_xrefs_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state) {
+	rz_return_val_if_fail(core && state, false);
+
+	RzPVector *l = rz_core_bin_whole_strings(core, bf);
+	RzPVector *ll = rz_pvector_new(NULL);
+
+	void **iter;
+	rz_pvector_foreach (l, iter) {
+		RzBinString *string = *iter;
+		RzList *list = rz_analysis_xrefs_get_to(core->analysis, string->paddr);
+		RzAnalysisXRef *xref;
+		RzListIter *iterator;
+		rz_list_foreach (list, iterator, xref) {
+			switch (xref->type) {
+			case RZ_ANALYSIS_XREF_TYPE_CODE:
+			case RZ_ANALYSIS_XREF_TYPE_DATA:
+				if (!rz_pvector_contains(ll, string)) {
+					rz_pvector_push_front(ll, string);
path: librz/core/cbin.c
user: login: ahmed-kamal2004
body: yes, this will be nicer approach, will test it.
created_at: 2025-04-01T15:13:06Z
author_association: MEMBER
diff_hunk: @@ -2946,6 +2946,36 @@ RZ_API bool rz_core_bin_whole_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL
 	return res;
 }
 
+RZ_IPI bool rz_core_bin_xrefs_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state) {
+	rz_return_val_if_fail(core && state, false);
+
+	RzPVector *l = rz_core_bin_whole_strings(core, bf);
+	RzPVector *ll = rz_pvector_new(NULL);
path: librz/core/cbin.c
user: login: Rot127
body: You can check for leaks by building with ASAN or using valgrind.
created_at: 2025-04-01T15:19:35Z
author_association: MEMBER
diff_hunk: @@ -2946,6 +2946,37 @@ RZ_API bool rz_core_bin_whole_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL
 	return res;
 }
 
+RZ_IPI bool rz_core_bin_xrefs_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state) {
+	rz_return_val_if_fail(core && state, false);
+
+	RzPVector *whole_strings = rz_core_bin_whole_strings(core, bf);
+	RzPVector *xrefs_strings = rz_pvector_new((RzPVectorFree)rz_bin_string_free);
path: librz/core/cbin.c
user: login: wargio
body: check for null ptr
created_at: 2025-04-16T12:51:48Z
author_association: MEMBER
diff_hunk: @@ -4648,6 +4648,17 @@ EXPECT=<<EOF
 EOF
 RUN
 
+NAME=izx
+FILE=bins/arm/elf/hello_world 
+CMDS=aaa;izx
+EXPECT=<<EOF
+nth      paddr      vaddr len size section type  string        
+---------------------------------------------------------------
+ 19 0x00000574 0x00000574  12   13 .rodata ascii Hello world!
+ 13 0x00000494 0x00000494  10   11 .text   ascii \bH\tKxD\tJ{D
path: test/db/cmd/cmd_i
user: login: wargio
body: I would say to not print text out of exec maps
created_at: 2025-04-17T09:59:53Z
author_association: MEMBER
diff_hunk: @@ -4648,6 +4648,17 @@ EXPECT=<<EOF
 EOF
 RUN
 
+NAME=izx
+FILE=bins/arm/elf/hello_world 
+CMDS=aaa;izx
+EXPECT=<<EOF
+nth      paddr      vaddr len size section type  string        
+---------------------------------------------------------------
+ 19 0x00000574 0x00000574  12   13 .rodata ascii Hello world!
+ 13 0x00000494 0x00000494  10   11 .text   ascii \bH\tKxD\tJ{D
path: test/db/cmd/cmd_i
user: login: ahmed-kamal2004
body: You mean `nth` `paddr` and others ?

Yes, this will be nicer, but how ? I consider maybe using `izxq` , what do you think ?
created_at: 2025-04-17T10:32:42Z
author_association: MEMBER
diff_hunk: @@ -4648,6 +4648,17 @@ EXPECT=<<EOF
 EOF
 RUN
 
+NAME=izx
+FILE=bins/arm/elf/hello_world 
+CMDS=aaa;izx
+EXPECT=<<EOF
+nth      paddr      vaddr len size section type  string        
+---------------------------------------------------------------
+ 19 0x00000574 0x00000574  12   13 .rodata ascii Hello world!
+ 13 0x00000494 0x00000494  10   11 .text   ascii \bH\tKxD\tJ{D
path: test/db/cmd/cmd_i
user: login: ahmed-kamal2004
body: I used `izxq`
created_at: 2025-04-18T09:14:34Z
author_association: MEMBER
diff_hunk: @@ -2946,6 +2946,42 @@ RZ_API bool rz_core_bin_whole_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL
 	return res;
 }
 
+RZ_API bool rz_core_bin_xrefs_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state) {
+	rz_return_val_if_fail(core && state, false);
+
+	RzPVector *whole_strings = rz_core_bin_whole_strings(core, bf);
+
+	if (!whole_strings) {
+		return false;
+	}
+
+	RzPVector *xrefs_strings = rz_pvector_new((RzPVectorFree)rz_bin_string_free);
path: librz/core/cbin.c
user: login: wargio
body: check for null here.
created_at: 2025-04-18T11:03:34Z
author_association: MEMBER
diff_hunk: @@ -2946,6 +2946,42 @@ RZ_API bool rz_core_bin_whole_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL
 	return res;
 }
 
+RZ_API bool rz_core_bin_xrefs_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state) {
+	rz_return_val_if_fail(core && state, false);
+
+	RzPVector *whole_strings = rz_core_bin_whole_strings(core, bf);
+
+	if (!whole_strings) {
+		return false;
+	}
+
+	RzPVector *xrefs_strings = rz_pvector_new((RzPVectorFree)rz_bin_string_free);
path: librz/core/cbin.c
user: login: ahmed-kamal2004
body: for `xrefs_strings` ? it should be empty, so i believe it can't be `null`,  what do you think ?
created_at: 2025-04-18T11:28:37Z
author_association: MEMBER
diff_hunk: @@ -2946,6 +2946,42 @@ RZ_API bool rz_core_bin_whole_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL
 	return res;
 }
 
+RZ_API bool rz_core_bin_xrefs_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state) {
+	rz_return_val_if_fail(core && state, false);
+
+	RzPVector *whole_strings = rz_core_bin_whole_strings(core, bf);
+
+	if (!whole_strings) {
+		return false;
+	}
+
+	RzPVector *xrefs_strings = rz_pvector_new((RzPVectorFree)rz_bin_string_free);
path: librz/core/cbin.c
user: login: wargio
body: You should check for null because it can be if the OS fails to allocate memory (I.e. Out of memory)
created_at: 2025-04-18T16:04:35Z
author_association: MEMBER
diff_hunk: @@ -2946,6 +2946,42 @@ RZ_API bool rz_core_bin_whole_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL
 	return res;
 }
 
+RZ_API bool rz_core_bin_xrefs_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzBinFile *bf, RZ_NONNULL RzCmdStateOutput *state) {
+	rz_return_val_if_fail(core && state, false);
+
+	RzPVector *whole_strings = rz_core_bin_whole_strings(core, bf);
+
+	if (!whole_strings) {
+		return false;
+	}
+
+	RzPVector *xrefs_strings = rz_pvector_new((RzPVectorFree)rz_bin_string_free);
path: librz/core/cbin.c
user: login: ahmed-kamal2004
body: Thanks for this info, perfect, I didn't think about this before, this makes Rizin at least doesn't make abnormal behaviour on devices with low ram.
created_at: 2025-04-18T16:31:56Z
author_association: MEMBER
diff_hunk: @@ -2957,6 +2957,10 @@ RZ_API bool rz_core_bin_xrefs_strings_print(RZ_NONNULL RzCore *core, RZ_NONNULL
 
 	RzPVector *xrefs_strings = rz_pvector_new((RzPVectorFree)rz_bin_string_free);
 
+	if (!xrefs_strings) {
+		return false;
path: librz/core/cbin.c
user: login: wargio
body: you need to call `rz_pvector_free(whole_strings);` before returning.
created_at: 2025-04-19T10:43:09Z
author_association: MEMBER

PR comments:
user: login: ahmed-kamal2004
created_at: 2025-04-01T14:57:18Z
body: I am seeking review on the approach and anything could be added to the PR would be great :rocket: 
author_association: MEMBER
user: login: ahmed-kamal2004
created_at: 2025-04-01T15:03:00Z
body: the clang-format tests failed, I will check it again
author_association: MEMBER
user: login: ahmed-kamal2004
created_at: 2025-04-16T07:30:11Z
body: forgot about tests :), but there is a good point, the clang-format passed :rocket: , will write tests now
author_association: MEMBER
user: login: ahmed-kamal2004
created_at: 2025-04-17T07:30:23Z
body: I think I will need to update the Book, once this PR is merged.
author_association: MEMBER
user: login: ahmed-kamal2004
created_at: 2025-04-20T20:11:35Z
body: @notxvilka well, I think I will do it in a new PR, the new one will a refactoring one.
author_association: MEMBER