From 2541aef71a2380379a6c41334eb0a189e0cbfc67 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Sun, 8 Mar 2026 11:13:40 -0600 Subject: [PATCH] Add symbol kind and structured flags to diff proto output (#337) * Add symbol kind to diff proto output Expose SymbolKind (Function, Object, Section, Unknown) in the DiffSymbol proto message, allowing CLI oneshot diff consumers to distinguish symbol types without inferring from instruction/data presence. * Stop filtering symbols from diff output, replace flags bitmask with message Remove the symbol filter (size == 0 / Ignored) from DiffObject so all symbols are emitted. This fixes target_symbol indices being invalid after filtering. Replace the DiffSymbolFlag bitmask enum + uint32 field with a DiffSymbolFlags message of booleans, adding ignored and size_inferred flags so consumers can filter on their end. --- objdiff-core/protos/diff.proto | 27 ++++++++++----- objdiff-core/protos/proto_descriptor.bin | Bin 17936 -> 18566 bytes objdiff-core/src/bindings/diff.rs | 41 ++++++++++++----------- 3 files changed, 39 insertions(+), 29 deletions(-) diff --git a/objdiff-core/protos/diff.proto b/objdiff-core/protos/diff.proto index 56dfa27..afb025a 100644 --- a/objdiff-core/protos/diff.proto +++ b/objdiff-core/protos/diff.proto @@ -39,7 +39,8 @@ message DiffSymbol { optional string demangled_name = 2; uint64 address = 3; uint64 size = 4; - uint32 flags = 5; + DiffSymbolFlags flags = 5; + DiffSymbolKind kind = 10; // The symbol index in the _other_ object that this symbol was diffed against optional uint32 target_symbol = 6; optional float match_percent = 7; @@ -49,14 +50,22 @@ message DiffSymbol { repeated DiffDataSegment data_diff = 9; } -// Symbol visibility flags (bitmask) -enum DiffSymbolFlag { - SYMBOL_NONE = 0; - SYMBOL_GLOBAL = 1; - SYMBOL_LOCAL = 2; - SYMBOL_WEAK = 4; - SYMBOL_COMMON = 8; - SYMBOL_HIDDEN = 16; +enum DiffSymbolKind { + SYMBOL_UNKNOWN = 0; + SYMBOL_FUNCTION = 1; + SYMBOL_OBJECT = 2; + SYMBOL_SECTION = 3; +} + +// Symbol flags +message DiffSymbolFlags { + bool global = 1; + bool local = 2; + bool weak = 3; + bool common = 4; + bool hidden = 5; + bool ignored = 6; + bool size_inferred = 7; } // A single instruction diff row diff --git a/objdiff-core/protos/proto_descriptor.bin b/objdiff-core/protos/proto_descriptor.bin index ac74171896c4bc2f696e72801a953341187e5474..ce62f84c09b40b29ccf7d12b8f30f0c1c5f52cce 100644 GIT binary patch delta 4016 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 Bmj?g< delta 3415 zcmZph$T*>gk(uk2(?;ePCdRpw6PRj5MYvegauU;vC0G?0HF$#{oXt+me2kk#SnJL5nS+(H3o+|WHWxOvVP_Fy)`Q!}&L+gH$1Mxh!p*?xoX@d>m5Mnl%yh2zriGxLm*#K?;2b&PH0k;%X3kRbRvw^e@JXoXnC+1#qM*Xe4Ep`=*^Eg9D#Zxq@xypbLd<4D!cc`wLd@n& z;7DR+WCCe3X97nHhzF7r6oM*b7Gkzw0$E+p%F4*Z%n0Jb>}F;XVzz+W%_78X3AdYt z5yXSp&B7$aYzeoURfyS&NfhcVRz?sHrjV6Mh}lX=giD)?iG@Xo#g4&=QA%FHQK2|9 zZ*sMmTs_EGI}Rz3+gMnb7=)PZnIu65fjDd+9wgbYfCI^%8ypfKIc6bddvOVCpa67`R)eWz77Af@(A0vO!X(7($fOUIV`2gEV5Ts! z2{AizE5hU$g_s?cAZdt&iHTW=*-=-IONR@TH&|R5f+pvPYt*wc3NgEKh=a{$1$oR3 z5<)DjObo0-%x=&u#0vJ98z&@zvobL-3o*M1i$Jw83NgEb;@_Q^?FK zE-5NaF3HT#Qz%F*D&gYd;$mh2X%6L(=HlUEVPWH75Ml{qif0C=6E+S|z7FHy;o`Cc zNrKWq#N3WyLE;gSPuViaPIVv&*(RPZlI&QD3z z&&^BC&CknBhUo>R?YF~_jTOK~aKITodt z=BDPAz{~)p?idy^h^xV6M~pb6xMKsS?ig7)aJ;gCl1AKQXKB59HYR3PA?7$1NNQvQ zCx$p^dSU}7hB#3%E-o%67Iq<)B!+ZGaA1K7-y{wpu-Di@;gP~5CMBrg3-yyiaY<2T zUOL2C?BGC3fu>k?a3G~{LaGh+7;q@1h=_8@aUB~szN?Es1!V1 zU?zcbP8!@KP$7`U2`->OTA78I(}aY%RJoW~ID}ZT7|JL6$|&lAiuo)KP$;mlaDd`9 zo2d*EuN>fb&F0|dQsrV{;Q)Cfck&z=MFS47i*upT$^mw9E;N;KfE}DGBFd!>*2E~p zoIm-kjIsd-I9un#HGv$L&kZieSvZ&&nT441#l*o0hy#?Z3nx3sn$~lGb8{hF6UhIC zaGOA}R45|KB?-2PS%|rqMOcbQAt*H`KRFSUd?CTY0gl3AXcTgQqp%oSm2-fjuvkzC zoEbSlg<&a+w3Lj3Q&D1G@?=*@X#);WX~$d&cLOLdmvTcA5eE|}FPBP6aj9@Iv2Y5p zR58>~c9fHuJVBhLo|93Cxr##!T*7gJLa!QH!f}GbuNoRpoZ#@QhL&)g;P9)4R81_L zAP?6tiGx!tCpZLa;MzbTSOZOpoZt|w5rx^tB*a`_%LK};tSp@1K&*x91DRRN3Go0Y zINjGuLh2<>P>9w+DpwXxaIn=eu|q8fRiJeokPOHP4z@aQuraZ439&UXGPE%=N=Ylg zvYbN7Aos6uYnt_Ft31oH`Ba;9~2Z+Zg z#L~sc#0}#zfw+92yZ}>-gRfwgZkx2romX#6A73PxS`{oXW_-1LHD-6!QykaanVL^fC#tOrLD3WNyL@N{KAf8JResDnX$+oskn9 zKrGy#w8%1@Q9ux!n|OrSW-~G@oV-9uzMh9sh-Ee-2c(qZ0r_JNBa;Hy5FRE5HX)Wd z(3of80sCVPqo6cQmKh`~Cl9W;ct94;g#`f*6C;}t%UoCx@PKL+mbtJX-~nYRmbr{V z!dzS?Tr4a+ps1cd*+bbNfd}l5`7nR*fT|Lf`HY<46a-SpEW|RO5t4#fc$k=lSQfy- ijt7*hKwL-=@PJAqmIaKQkg($ceiBDw! diff --git a/objdiff-core/src/bindings/diff.rs b/objdiff-core/src/bindings/diff.rs index 9a9c36d..0dd22b6 100644 --- a/objdiff-core/src/bindings/diff.rs +++ b/objdiff-core/src/bindings/diff.rs @@ -43,9 +43,6 @@ impl DiffObject { let mut symbols = Vec::with_capacity(obj.symbols.len()); for (symbol_idx, symbol) in obj.symbols.iter().enumerate() { let symbol_diff = &diff.symbols[symbol_idx]; - if symbol.size == 0 || symbol.flags.contains(SymbolFlag::Ignored) { - continue; - } symbols.push(DiffSymbol::new(obj, symbol_idx, symbol, symbol_diff, diff_config)?); } @@ -112,6 +109,7 @@ impl DiffSymbol { address: symbol.address, size: symbol.size, flags: symbol_flags(&symbol.flags), + kind: DiffSymbolKind::from(symbol.kind) as i32, // Diff information target_symbol: symbol_diff.target_symbol.map(|i| i as u32), match_percent: symbol_diff.match_percent, @@ -121,24 +119,27 @@ impl DiffSymbol { } } -fn symbol_flags(flags: &obj::SymbolFlagSet) -> u32 { - let mut result = 0u32; - if flags.contains(SymbolFlag::Global) { - result |= DiffSymbolFlag::SymbolGlobal as u32; +impl From for DiffSymbolKind { + fn from(value: obj::SymbolKind) -> Self { + match value { + obj::SymbolKind::Unknown => DiffSymbolKind::SymbolUnknown, + obj::SymbolKind::Function => DiffSymbolKind::SymbolFunction, + obj::SymbolKind::Object => DiffSymbolKind::SymbolObject, + obj::SymbolKind::Section => DiffSymbolKind::SymbolSection, + } } - if flags.contains(SymbolFlag::Local) { - result |= DiffSymbolFlag::SymbolLocal as u32; - } - if flags.contains(SymbolFlag::Weak) { - result |= DiffSymbolFlag::SymbolWeak as u32; - } - if flags.contains(SymbolFlag::Common) { - result |= DiffSymbolFlag::SymbolCommon as u32; - } - if flags.contains(SymbolFlag::Hidden) { - result |= DiffSymbolFlag::SymbolHidden as u32; - } - result +} + +fn symbol_flags(flags: &obj::SymbolFlagSet) -> Option { + Some(DiffSymbolFlags { + global: flags.contains(SymbolFlag::Global), + local: flags.contains(SymbolFlag::Local), + weak: flags.contains(SymbolFlag::Weak), + common: flags.contains(SymbolFlag::Common), + hidden: flags.contains(SymbolFlag::Hidden), + ignored: flags.contains(SymbolFlag::Ignored), + size_inferred: flags.contains(SymbolFlag::SizeInferred), + }) } impl DiffInstructionRow {