[Lldb-commits] [lldb] [lldb][AArch64] Handle core file tag segments missing tag data (PR #145338)
David Spickett via lldb-commits
lldb-commits at lists.llvm.org
Mon Jun 23 08:10:12 PDT 2025
https://github.com/DavidSpickett updated https://github.com/llvm/llvm-project/pull/145338
>From 4b5a55eb2d7e8430eca4b76644b08fe705fbfec6 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Mon, 23 Jun 2025 14:29:53 +0000
Subject: [PATCH 1/2] [lldb][AArch64] Handle core file tag segments missing tag
data
In the same way that memory regions may be known from a core file
but not readable, tag segments can also have no content. For example:
$ readelf --segments core
<...>
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
<...>
LOAD 0x0000000000002000 0x0000ffff93899000 0x0000000000000000
0x0000000000000000 0x0000000000001000 RW 0x1000
<...>
LOPROC+0x2 0x0000000000008000 0x0000ffff93899000 0x0000000000000000
0x0000000000000000 0x0000000000001000 0x0
This happens if you have a restricted coredump filter or size limit.
The area of virtual memory this segment covers is 0x1000, or 4096
bytes aka one tagged page. It's FileSiz would normally be 0x80.
Tags are packed 2 per byte and granules are 16 bytes. 4096 / 16 / 2 = 128
or 0x80.
But here it has no data, and in theory a corrupt file might have some
data but not all. This triggered an assert in UnpackTagsFromCoreFileSegment
and crashed lldb.
To fix this I have made UnpackTagsFromCoreFileSegment return an expected
and returned an error in this case instead of asserting. This will be seen
by the user, as shown in the added API test.
---
lldb/include/lldb/Target/MemoryTagManager.h | 12 +++--
.../Utility/MemoryTagManagerAArch64MTE.cpp | 10 ++--
.../Utility/MemoryTagManagerAArch64MTE.h | 2 +-
.../TestAArch64LinuxMTEMemoryTagCoreFile.py | 24 +++++++++
.../aarch64/mte_core_file/core.mte.notags | Bin 0 -> 32768 bytes
.../MemoryTagManagerAArch64MTETest.cpp | 51 ++++++++++++++----
6 files changed, 81 insertions(+), 18 deletions(-)
create mode 100644 lldb/test/API/linux/aarch64/mte_core_file/core.mte.notags
diff --git a/lldb/include/lldb/Target/MemoryTagManager.h b/lldb/include/lldb/Target/MemoryTagManager.h
index 6bd4180fff703..587e5ef4199d4 100644
--- a/lldb/include/lldb/Target/MemoryTagManager.h
+++ b/lldb/include/lldb/Target/MemoryTagManager.h
@@ -122,11 +122,15 @@ class MemoryTagManager {
//
// 'reader' will always be a wrapper around a CoreFile in real use
// but allows testing without having to mock a CoreFile.
+ //
+ // This call may fail in the case that the core file segment does not contain
+ // enough data to read all the tags.
typedef std::function<size_t(lldb::offset_t, size_t, void *)> CoreReaderFn;
- std::vector<lldb::addr_t> virtual UnpackTagsFromCoreFileSegment(
- CoreReaderFn reader, lldb::addr_t tag_segment_virtual_address,
- lldb::addr_t tag_segment_data_address, lldb::addr_t addr,
- size_t len) const = 0;
+ llvm::
+ Expected<std::vector<lldb::addr_t>> virtual UnpackTagsFromCoreFileSegment(
+ CoreReaderFn reader, lldb::addr_t tag_segment_virtual_address,
+ lldb::addr_t tag_segment_data_address, lldb::addr_t addr,
+ size_t len) const = 0;
// Pack uncompressed tags into their storage format (e.g. for gdb QMemTags).
// Checks that each tag is within the expected value range.
diff --git a/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp b/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp
index 7e25bc4ea2a28..9f60675e51904 100644
--- a/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp
+++ b/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.cpp
@@ -247,7 +247,7 @@ MemoryTagManagerAArch64MTE::UnpackTagsData(const std::vector<uint8_t> &tags,
return unpacked;
}
-std::vector<lldb::addr_t>
+llvm::Expected<std::vector<lldb::addr_t>>
MemoryTagManagerAArch64MTE::UnpackTagsFromCoreFileSegment(
CoreReaderFn reader, lldb::addr_t tag_segment_virtual_address,
lldb::addr_t tag_segment_data_address, lldb::addr_t addr,
@@ -290,8 +290,12 @@ MemoryTagManagerAArch64MTE::UnpackTagsFromCoreFileSegment(
const size_t bytes_copied =
reader(tag_segment_data_address + file_offset_in_bytes, tag_bytes_to_read,
tag_data.data());
- UNUSED_IF_ASSERT_DISABLED(bytes_copied);
- assert(bytes_copied == tag_bytes_to_read);
+ if (bytes_copied != tag_bytes_to_read) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Could not read tags from core file segment. Segment "
+ "is missing some or all tag data.");
+ }
std::vector<lldb::addr_t> tags;
tags.reserve(2 * tag_data.size());
diff --git a/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h b/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h
index 365e176e5b1da..79d24ce78ecee 100644
--- a/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h
+++ b/lldb/source/Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h
@@ -44,7 +44,7 @@ class MemoryTagManagerAArch64MTE : public MemoryTagManager {
UnpackTagsData(const std::vector<uint8_t> &tags,
size_t granules = 0) const override;
- std::vector<lldb::addr_t>
+ llvm::Expected<std::vector<lldb::addr_t>>
UnpackTagsFromCoreFileSegment(CoreReaderFn reader,
lldb::addr_t tag_segment_virtual_address,
lldb::addr_t tag_segment_data_address,
diff --git a/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py b/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py
index a9879f67d8b8f..467881430e778 100644
--- a/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py
+++ b/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py
@@ -248,3 +248,27 @@ def test_mte_ctrl_register(self):
"TCF: 0 = TCF_NONE, 1 = TCF_SYNC, 2 = TCF_ASYNC, 3 = TCF_ASYMM"
],
)
+
+ @skipIfLLVMTargetMissing("AArch64")
+ def test_mte_no_tags(self):
+ """Test that we handle there being a tag segment but that segment does
+ not contain any tag data. This can happen when the core is dumped
+ with a restrictive limit or filter."""
+ self.runCmd("target create --core core.mte.notags")
+
+ # TODO: regenerate all the core files once MTE4 support has landed.
+ MTE_BUF_ADDR = 0xFFFFA4AF3000
+
+ # We can see which memory was tagged.
+ self.expect(
+ f"memory region {MTE_BUF_ADDR}", substrs=["memory tagging: enabled"]
+ )
+
+ # We cannot read those tags.
+ self.expect(
+ f"memory tag read {MTE_BUF_ADDR}",
+ substrs=[
+ "Could not read tags from core file segment. Segment is missing some or all tag data."
+ ],
+ error=True,
+ )
diff --git a/lldb/test/API/linux/aarch64/mte_core_file/core.mte.notags b/lldb/test/API/linux/aarch64/mte_core_file/core.mte.notags
new file mode 100644
index 0000000000000000000000000000000000000000..8f9d60668a84d99b425ab7bfe20c02b67e153542
GIT binary patch
literal 32768
zcmeI5dr(x at 8Nk2Yy9-Oix;|2gA>r~cqGMK2V<b(7%dV)j6dkh3WRgjjbr*#IyShNC
z(TuA?d~BKu$+XpEMo>|gaT2FvTCwdw%%dizQ-#`T)6N9VLo=ogU>>02?f2b#4(u+F
zv?iTN+jH>V^Z3qp&Ub$2JLlf(A7?k_7cMp$48Vg4eg(rh0EG)8Vg(k$6qYx!xQQns
z>QOQyF}i?Pqdv?elIcd_FCVtH>Zz!^mE~AWdRiMYul4r7tQSWrT+e!gdL_?Z8Qo5!
zZcv1s(c^2_uc~^LsQb>O5qesI%xdinkFM9l<PrTvaS67LuBVLDi{jEThMxQ-dfj8_
zb&S-D;vyd&-OeK;c}CeOzc{)c;{g#|qV%$EP)`{{Zxk+3^H36_r!XEoj<8eXQo`g-
zF?up9=W&Fd)?bjxJ7V-$@vz_P1+<PdE<skI`v&#oq`^`B+8RB7m|Ly&#QXcQd0=J{
zlWk}$+3Q$VoKMB$=*B{1nwL$-%JFzne1;cd{QQK73?|Rq9-SX6$M?Di|2jIO-z4aJ
z*U=UF-f$CZ$UWb^a&A^u7TK-^HfApW7B83ec6)A{7R8e5@%VJYPosSPVv1gWNIqWQ
z(-bzBQ!H#xJrcb(`<dQpR-c<ua=YH%HKv!v@@v`nuwDt(<^5 at MgLw%rJ~vQIH88{}
zT67VGbj8kz+vcyWu~pTSYPA4tbB0P}R`iu3vMq>L!IFaexNY255?IUDv3!upzwSu0
z3E|PY<2I%8PMUNdn8)&~C+P{c%wenA at G)`M)+~vbV4_|Pyey`<prEklskS#@exX*%
zp1GLj4B}ZiuzlFV^DO4|AYS(+&XDGm0)M>o{CK at sn{!HXALsI^OwOZQSYlzC?t9Z%
ze$zQu(3Awh+gP5DD~07hnxog}OL{5Ozm>_8V`7=*V<VcA0B%nCg$0ZGobdI at 84tai
zSYzK&*gHh*y9Ce6x}2{U0QL?L`%LF~_RQYS75FopJ(Fo4)B?*xx4y2Q;^q8VdisT^
zeF8ezzQy*1S*#ggd4MBY{n at O1PMN=|bdJ~kSoP}itnA^12{$09tq#noEMGCl?GAX#
z7R<l1vfNj at _RdwlS}OI}s{OVFFz1_7$;%96=8}EcUufUgqoA)#dSv3ip}k>xOu*gJ
zwW4<AJ at WL`LoNy(`lRvoq2+o2CiIN_BUumVPirmK7BAj-tT!d at -%tXy_tUm-z)iid
zpy>VwF)cq3{Z2x4EVv&SBkEZBrj4 at y=fK%Wg3SmwAU5=_V2WU)V&Fa(7g4S&Z)9z3
z)ZR(xz2T;aI{dk;F-KWKgzT!Szjbigga{dbA0Zii8CxS{m=!?~5CjAPK|l}?1Ox#=
zKoAfF1OY)n5D)|e0YN|z5CjAPK|l}?1Ox#=KoAfF1OY)n5D)|e0YN|z5CjAPK|l}?
z1Ox#=KoAfF1OY)n5D)|e0YN|z5CjAPK|l}?1Ox#=KoAfF1OY)n5D)|e0YN|z5CjAP
zK|l}?1Ox#=KoAfF1OY)n5csbourcQRe`$>K|NqPn^2Jfo`Tr8$$K%1Fbo4Bpp*vPc
zVtPE5Sw%YM6p!|Ue(mhhk at 3(W)9h?pel9WT(6y5q7$tV<#lT~#OM%WurLzUeR%(*Y
z7mN(l96v*q>qN?V`Uy--gx(P+`P;C3682EY4lt}_3X3qdV)@@#IUfg|ZAkT-7`(%5
zoDZ>bU=_D9qex8kxsg9-;|G_kqBP(ut#o-R{hkWfs?wU8@~YC|VpiZ^>2<FgE*+{I
zD6JkY4b-@*%U1<TYia|&;ZkfN;P!d_RiGc<`<NF`#nleR)ea$b&9yDC&C5aij1hkZ
zq)dO!?f)20=cm(o%vE?%ps^V7zWtOdo}aBwTqzKHDx+a9DY_pF%Ub51SGOL2(fhM0
zTb{l)ZO43gi{_5cQ6ZftjCrueX>+P!#M at 9g$-W?@+zV?in!%X{!D5efQ?Xs{nC87O
zXmx<}s1gUxCqZd at 1<~JOhP&Hyq_dk%O4|w(%ukV}vnRU0b2cB0Z@%xD9%=_=pnka=
zdg`zeZppNVw`MqIQvGeH{|;CxULI7P3M8JoAjRYH%j0&O&)wB&uRhoZneop-#v8j+
zz<8;^0M7SvcQx*R>R2DOPZy3f<T1fSk{?o4XN!^^nhp>Kw6{ZY{VDTX!A>0RA1S>B
zZ8O4=NgKgf(Jg^97xho8>QtBM)<83WGsOyPHeFYpG`=^n95yJ=#9 at 821sdwD=Fn!e
zb+bVq=Rq9L41j at yCX7umKx5g8au>u`yo_y7|J~RI at o+(01+k+3KE^WY$KkzhO?%|J
z)dQP%m!h6IL2q{j at w=i9 at mq}iKJeTTdI$TnY}nAX5-g!gWcWHVT*Vkxp?*7z*BI8J
zJd)$P$Z at mP9wv?s;)yJY+3R2o8PUcRkS=|QW9M8+X4iO18qX6-S}2Y2JWNcGMf^t_
zx`I{+)x+|(dP%oC4weoWO-nTn+ps*vV6HIWd;s!!A8n{BTh*@sg!0jb6WB)zm`C)h
z&!buE*Makx&iZ{C`z3b2Wbt`oh<Un9U4vHH3`gsc!9MiEmbhU*G{z76VI)WL!6##U
zupNEy9QvT0`Jf$r5Ser?LVNAV&W_w%V7fFDeGtdf*us3!4ra~&NJjqmI@;|yzP;Fy
zxHn+mu<tqhwUu3Q76`imUgAFK{rw;wWqo9l{DbRO@=5YXfV$nrj=VNx-3G7bwaF%o
zaeh9*u}1kV&K0qE70WYk9`<c2+k)I*QRCS<T;66>hy5sW9frDd8=g#B-nKP)dE2AY
z^TMUg_AvQx2=zA_B+ZZPaMP&|q_|mjNZ3I>M80E}<DRQavWM*%zuRqxxKInuV;tJ(
zit!;k`4{>Sl at pT#${nF!)11*>Vg#r6wL#pCj!dFGMasW!-HHroUn!lmsaVCe;z1TJ
zFh81#tZ8j37=yg2vnjr*FAv~oZp8X7IhognYkAfcY=3FQS|{J2{pX9~vWYssvyz-L
z)|HzsogG|%EIcSd!{z%7;ZGz(>!%MJ!=Fmf`k7>$MeSd$Hiz-t{oZSm)T-vfK+uwR
zT%HKdlG#clD8_~qlhV5l^LrFyuidib at k5yY+#`h-{`R^R(v_T)WC(Oy!I^q994*PP
z=iu79`||f|evu24FUdQf+5MxSp<$rH6wX6l-Sc2T#`v5c+DbBvIUp$mn;gnO3K%ZA
zCxf#--Ja7uPZ=;I20PQheCn!nbE^yB(iODVzB9P{d>p()HuLLkBOJZ_uAyPq7DIze
zg<jfYyQN!O9qQt)^U~zjbJEn-y#UV+V60qtyz!x_O5=J7Lb~jh)@~`e)d9iIU07#N
zx-rL$>EjZ-L^hFaI9HeQaBO>K7&W^-_c+1>6^p`GtMkK`@5>8+`mjAbxc=m!cH~TZ
zG(P=Wi6t>?!acJa?LQ|?X+1A}d)CP`eZEH1J1<RZt(VLpS2FY_SitF!;fx7wabI(E
zrJ^sU_B_$mROan3smSPWFU#n!lc6CO*Q^`;)7|q#V+-a>(xIUR3?Z~3lxI;I_kwl7
zKHOJQt#C$K1jpL($~8eRK3tqwzAn{*<r%QH9j{I3m(8H$7yxqG at e1NRte1?Tha}@E
ze4397BAXWU(ai(uT}`H7;~y}MY<d-o@^}Y6iz0o6+9y6uhG64sSdW;E#$hamu0-fP
ziEYq4y3k(bs_Hx^8C$!sEh?ilJ>N>Qpur7>25C~T(`d%$J9PAIkzio+IA}}3v64@{
zjC`mc+>1K*GFz@;9CYZ<JcB9N8ARWqX9=Gl(mO|MHZfRiMn9ynKTLi5m9`WUtZ7Eu
z$RD^byn!<E>2CDtLQL<$wj<?egSOwhGNiK>?+2YHfBaUT#df&wP~uPe61;!!-2TE_
zeFd{$>?=4>-)FkbQj~F9QqlB7O5u{VN at A7?CRnHKED9#?FKSM1DLRpSpy=J?gGF`5
zU at _D+7kQFppT|<-v)An_%1%!6r9LowS?c21ev++0S^5K+%hDHT`iJE+P(H(-DjR%u
z#pv^tNWQPsP6=yAmV9*<SmVaIg1Y at hsdX(y_PPT_p1OlYAVcAWx}G1RUpC+~vbT9a
zbuL+p9~bYzG6P;lyd=ELc*WsG>nQk{s$RoQaWYseM?Y89ewOa(SJh8g`n>^F?P2MK
zS5@`->#90UJK=ozcS-m=DgT`n{;J5|FE6qJ_L>eIxBw{d?}sFo=Re4>Ll+PIMiIT|
zQ$U~cQ~aQj?g02hKU$t;p at -$a#|!jo|FJv&?i#CuB at V|ua%NtjO2)Tv+3ELJddl48
zJ~?~7ZLY1jv@%=HwAYqbdS!Q@>P{@YYwpaMx-eUwn>BZSc6K&?64<KCs%ru@?iFAw
zb61yv&AZN5y{<}+YXV at y9|EyGRvM at -_xqwUE-%=8e*ASHTTSWO8nC%5Ys!7tRIR55
zt5$0bxU0%NU<>%Y?ix4PJpQVxQeVwj<N0^X=_eCt&iQn3Kj3i|Ymmz=EYJOhewT;Z
z;BxLKJU+zg({~QJ5ZCAaatoG`jO%m1<1zO$tfB?xhCB<Yn8M at x{al~>6_5GnJeSAD
z^gT;H%FDUm@^~TZiQCBS=LUQi6ZFZ;^<%%+ at dF|%aBjTNfe9KDUuPN&5>kg4jwR?Z
zzso$q;sT6GpZ9-^{XYYb?~SP+%a6Xpsc+WZi2tY18jq0k@$-GegEDH9efC2?`(Y#=
z%P5NsT%X4kC?tLEXS^=|f0TS)z+!HHWXx at ktojI>_}GQQ^&;zvv>+e|2m*qDARq_`
S0)l`bAP5Kog24X{fqw$@NM;oP
literal 0
HcmV?d00001
diff --git a/lldb/unittests/Process/Utility/MemoryTagManagerAArch64MTETest.cpp b/lldb/unittests/Process/Utility/MemoryTagManagerAArch64MTETest.cpp
index 40d7c3601ccfd..30199bfe5c254 100644
--- a/lldb/unittests/Process/Utility/MemoryTagManagerAArch64MTETest.cpp
+++ b/lldb/unittests/Process/Utility/MemoryTagManagerAArch64MTETest.cpp
@@ -87,31 +87,38 @@ TEST(MemoryTagManagerAArch64MTETest, UnpackTagsFromCoreFileSegment) {
std::vector<uint8_t> tags_data;
MemoryTagManager::CoreReaderFn reader =
[&tags_data](lldb::offset_t offset, size_t length, void *dst) {
+ if ((offset + length) >= tags_data.size())
+ length = tags_data.size() - offset;
+
std::memcpy(dst, tags_data.data() + offset, length);
return length;
};
// Zero length is ok.
- std::vector<lldb::addr_t> tags =
+ llvm::Expected<std::vector<lldb::addr_t>> tags =
manager.UnpackTagsFromCoreFileSegment(reader, 0, 0, 0, 0);
- ASSERT_EQ(tags.size(), (size_t)0);
+ ASSERT_THAT_EXPECTED(tags, llvm::Succeeded());
+ ASSERT_EQ(tags->size(), (size_t)0);
// In the simplest case we read 2 tags which are in the same byte.
tags_data.push_back(0x21);
// The least significant bits are the first tag in memory.
std::vector<lldb::addr_t> expected{1, 2};
tags = manager.UnpackTagsFromCoreFileSegment(reader, 0, 0, 0, 32);
- ASSERT_THAT(expected, testing::ContainerEq(tags));
+ ASSERT_THAT_EXPECTED(tags, llvm::Succeeded());
+ ASSERT_THAT(expected, testing::ContainerEq(*tags));
// If we read just one then it will have to trim off the second one.
expected = std::vector<lldb::addr_t>{1};
tags = manager.UnpackTagsFromCoreFileSegment(reader, 0, 0, 0, 16);
- ASSERT_THAT(expected, testing::ContainerEq(tags));
+ ASSERT_THAT_EXPECTED(tags, llvm::Succeeded());
+ ASSERT_THAT(expected, testing::ContainerEq(*tags));
// If we read the second tag only then the first one must be trimmed.
expected = std::vector<lldb::addr_t>{2};
tags = manager.UnpackTagsFromCoreFileSegment(reader, 0, 0, 16, 16);
- ASSERT_THAT(expected, testing::ContainerEq(tags));
+ ASSERT_THAT_EXPECTED(tags, llvm::Succeeded());
+ ASSERT_THAT(expected, testing::ContainerEq(*tags));
// This trimming logic applies if you read a larger set of tags.
tags_data = std::vector<uint8_t>{0x21, 0x43, 0x65, 0x87};
@@ -119,31 +126,55 @@ TEST(MemoryTagManagerAArch64MTETest, UnpackTagsFromCoreFileSegment) {
// Trailing tag should be trimmed.
expected = std::vector<lldb::addr_t>{1, 2, 3};
tags = manager.UnpackTagsFromCoreFileSegment(reader, 0, 0, 0, 48);
- ASSERT_THAT(expected, testing::ContainerEq(tags));
+ ASSERT_THAT_EXPECTED(tags, llvm::Succeeded());
+ ASSERT_THAT(expected, testing::ContainerEq(*tags));
// Leading tag should be trimmed.
expected = std::vector<lldb::addr_t>{2, 3, 4};
tags = manager.UnpackTagsFromCoreFileSegment(reader, 0, 0, 16, 48);
- ASSERT_THAT(expected, testing::ContainerEq(tags));
+ ASSERT_THAT_EXPECTED(tags, llvm::Succeeded());
+ ASSERT_THAT(expected, testing::ContainerEq(*tags));
// Leading and trailing trimmmed.
expected = std::vector<lldb::addr_t>{2, 3, 4, 5};
tags = manager.UnpackTagsFromCoreFileSegment(reader, 0, 0, 16, 64);
- ASSERT_THAT(expected, testing::ContainerEq(tags));
+ ASSERT_THAT_EXPECTED(tags, llvm::Succeeded());
+ ASSERT_THAT(expected, testing::ContainerEq(*tags));
// The address given is an offset into the whole file so the address requested
// from the reader should be beyond that.
tags_data = std::vector<uint8_t>{0xFF, 0xFF, 0x21, 0x43, 0x65, 0x87};
expected = std::vector<lldb::addr_t>{1, 2};
tags = manager.UnpackTagsFromCoreFileSegment(reader, 0, 2, 0, 32);
- ASSERT_THAT(expected, testing::ContainerEq(tags));
+ ASSERT_THAT_EXPECTED(tags, llvm::Succeeded());
+ ASSERT_THAT(expected, testing::ContainerEq(*tags));
// addr is a virtual address that we expect to be >= the tag segment's
// starting virtual address. So again an offset must be made from the
// difference.
expected = std::vector<lldb::addr_t>{3, 4};
tags = manager.UnpackTagsFromCoreFileSegment(reader, 32, 2, 64, 32);
- ASSERT_THAT(expected, testing::ContainerEq(tags));
+ ASSERT_THAT_EXPECTED(tags, llvm::Succeeded());
+ ASSERT_THAT(expected, testing::ContainerEq(*tags));
+
+ // Error when there is not enough data to decode tags.
+
+ // Read 1 tag from an offset just outside the segment's data.
+ tags_data = {0xAB};
+ tags = manager.UnpackTagsFromCoreFileSegment(reader, 0, 0, 32, 16);
+ const char *expected_err = "Could not read tags from core file segment. "
+ "Segment is missing some or all tag data.";
+ EXPECT_THAT_EXPECTED(tags, llvm::FailedWithMessage(expected_err));
+
+ // First 2 tags come from the segment, second 2 cannot be read.
+ tags_data.push_back(0xCD);
+ tags = manager.UnpackTagsFromCoreFileSegment(reader, 0, 0, 32, 64);
+ EXPECT_THAT_EXPECTED(tags, llvm::FailedWithMessage(expected_err));
+
+ // Segment is completely empty.
+ tags_data.clear();
+ tags = manager.UnpackTagsFromCoreFileSegment(reader, 0, 0, 0, 16);
+ EXPECT_THAT_EXPECTED(tags, llvm::FailedWithMessage(expected_err));
}
TEST(MemoryTagManagerAArch64MTETest, GetLogicalTag) {
>From 3f3783e0f4dcb1515e4b0ced056fb6cc74f78d75 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Mon, 23 Jun 2025 15:09:57 +0000
Subject: [PATCH 2/2] fix a word
---
lldb/include/lldb/Target/MemoryTagManager.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/include/lldb/Target/MemoryTagManager.h b/lldb/include/lldb/Target/MemoryTagManager.h
index 587e5ef4199d4..5b7219692d77f 100644
--- a/lldb/include/lldb/Target/MemoryTagManager.h
+++ b/lldb/include/lldb/Target/MemoryTagManager.h
@@ -123,7 +123,7 @@ class MemoryTagManager {
// 'reader' will always be a wrapper around a CoreFile in real use
// but allows testing without having to mock a CoreFile.
//
- // This call may fail in the case that the core file segment does not contain
+ // This call will fail in the case that the core file segment does not contain
// enough data to read all the tags.
typedef std::function<size_t(lldb::offset_t, size_t, void *)> CoreReaderFn;
llvm::
More information about the lldb-commits
mailing list