@@ -779,15 +779,44 @@ static int check_prepare_btf_string_fetch(char *typename,
779779
780780#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
781781
782+ static void store_entry_arg_at (struct fetch_insn * code , int argnum , int offset )
783+ {
784+ code [0 ].op = FETCH_OP_ARG ;
785+ code [0 ].param = argnum ;
786+ code [1 ].op = FETCH_OP_ST_EDATA ;
787+ code [1 ].offset = offset ;
788+ }
789+
790+ static int get_entry_arg_max_offset (struct probe_entry_arg * earg )
791+ {
792+ int i , max_offset = 0 ;
793+
794+ /*
795+ * earg->code[] array has an operation sequence which is run in
796+ * the entry handler.
797+ * The sequence stopped by FETCH_OP_END and each data stored in
798+ * the entry data buffer by FETCH_OP_ST_EDATA. The FETCH_OP_ST_EDATA
799+ * stores the data at the data buffer + its offset, and all data are
800+ * "unsigned long" size. The offset must be increased when a data is
801+ * stored. Thus we need to find the last FETCH_OP_ST_EDATA in the
802+ * code array.
803+ */
804+ for (i = 0 ; i < earg -> size - 1 && earg -> code [i ].op != FETCH_OP_END ; i ++ ) {
805+ if (earg -> code [i ].op == FETCH_OP_ST_EDATA )
806+ if (earg -> code [i ].offset > max_offset )
807+ max_offset = earg -> code [i ].offset ;
808+ }
809+ return max_offset ;
810+ }
811+
782812/*
783813 * Add the entry code to store the 'argnum'th parameter and return the offset
784814 * in the entry data buffer where the data will be stored.
785815 */
786816static int __store_entry_arg (struct trace_probe * tp , int argnum )
787817{
788818 struct probe_entry_arg * earg = tp -> entry_arg ;
789- bool match = false;
790- int i , offset ;
819+ int i , offset , last_offset = 0 ;
791820
792821 if (!earg ) {
793822 earg = kzalloc (sizeof (* tp -> entry_arg ), GFP_KERNEL );
@@ -804,78 +833,59 @@ static int __store_entry_arg(struct trace_probe *tp, int argnum)
804833 for (i = 0 ; i < earg -> size ; i ++ )
805834 earg -> code [i ].op = FETCH_OP_END ;
806835 tp -> entry_arg = earg ;
836+ store_entry_arg_at (earg -> code , argnum , 0 );
837+ return 0 ;
807838 }
808839
809840 /*
810- * The entry code array is repeating the pair of
811- * [FETCH_OP_ARG(argnum)][FETCH_OP_ST_EDATA(offset of entry data buffer)]
812- * and the rest of entries are filled with [FETCH_OP_END].
841+ * NOTE: if anyone change the following rule, please rewrite this.
842+ * The entry code array is filled with the pair of
843+ *
844+ * [FETCH_OP_ARG(argnum)]
845+ * [FETCH_OP_ST_EDATA(offset of entry data buffer)]
813846 *
814- * To reduce the redundant function parameter fetching, we scan the entry
815- * code array to find the FETCH_OP_ARG which already fetches the 'argnum'
816- * parameter. If it doesn't match, update 'offset' to find the last
817- * offset.
818- * If we find the FETCH_OP_END without matching FETCH_OP_ARG entry, we
819- * will save the entry with FETCH_OP_ARG and FETCH_OP_ST_EDATA, and
820- * return data offset so that caller can find the data offset in the entry
821- * data buffer.
847+ * and the rest of entries are filled with [FETCH_OP_END].
848+ * The offset should be incremented, thus the last pair should
849+ * have the largest offset.
822850 */
823- offset = 0 ;
824- for (i = 0 ; i < earg -> size - 1 ; i ++ ) {
825- switch (earg -> code [i ].op ) {
826- case FETCH_OP_END :
827- earg -> code [i ].op = FETCH_OP_ARG ;
828- earg -> code [i ].param = argnum ;
829- earg -> code [i + 1 ].op = FETCH_OP_ST_EDATA ;
830- earg -> code [i + 1 ].offset = offset ;
831- return offset ;
832- case FETCH_OP_ARG :
833- match = (earg -> code [i ].param == argnum );
834- break ;
835- case FETCH_OP_ST_EDATA :
836- offset = earg -> code [i ].offset ;
837- if (match )
838- return offset ;
839- offset += sizeof (unsigned long );
840- break ;
841- default :
842- break ;
843- }
851+
852+ /* Search the offset for the sprcified argnum. */
853+ for (i = 0 ; i < earg -> size - 1 && earg -> code [i ].op != FETCH_OP_END ; i += 2 ) {
854+ if (WARN_ON_ONCE (earg -> code [i ].op != FETCH_OP_ARG ))
855+ return - EINVAL ;
856+
857+ if (earg -> code [i ].param != argnum )
858+ continue ;
859+
860+ if (WARN_ON_ONCE (earg -> code [i + 1 ].op != FETCH_OP_ST_EDATA ))
861+ return - EINVAL ;
862+
863+ return earg -> code [i + 1 ].offset ;
844864 }
845- return - ENOSPC ;
865+ /* Not found, append new entry if possible. */
866+ if (i >= earg -> size - 1 )
867+ return - ENOSPC ;
868+
869+ /* The last entry must have the largest offset. */
870+ if (i != 0 ) {
871+ if (WARN_ON_ONCE (earg -> code [i - 1 ].op != FETCH_OP_ST_EDATA ))
872+ return - EINVAL ;
873+ last_offset = earg -> code [i - 1 ].offset ;
874+ }
875+
876+ offset = last_offset + sizeof (unsigned long );
877+ store_entry_arg_at (& earg -> code [i ], argnum , offset );
878+ return offset ;
846879}
847880
848881int traceprobe_get_entry_data_size (struct trace_probe * tp )
849882{
850883 struct probe_entry_arg * earg = tp -> entry_arg ;
851- int i , size = 0 ;
852884
853885 if (!earg )
854886 return 0 ;
855887
856- /*
857- * earg->code[] array has an operation sequence which is run in
858- * the entry handler.
859- * The sequence stopped by FETCH_OP_END and each data stored in
860- * the entry data buffer by FETCH_OP_ST_EDATA. The FETCH_OP_ST_EDATA
861- * stores the data at the data buffer + its offset, and all data are
862- * "unsigned long" size. The offset must be increased when a data is
863- * stored. Thus we need to find the last FETCH_OP_ST_EDATA in the
864- * code array.
865- */
866- for (i = 0 ; i < earg -> size ; i ++ ) {
867- switch (earg -> code [i ].op ) {
868- case FETCH_OP_END :
869- goto out ;
870- case FETCH_OP_ST_EDATA :
871- size = earg -> code [i ].offset + sizeof (unsigned long );
872- break ;
873- default :
874- break ;
875- }
876- }
877- out :
878- return size ;
888+ return get_entry_arg_max_offset (earg ) + sizeof (unsigned long );
879889}
880890
881891void store_trace_entry_data (void * edata , struct trace_probe * tp , struct pt_regs * regs )
0 commit comments