Instructions are data. Before a program runs, the build tools and operating system treat the program as data, e.g. as a data file. In order to load the program into memory, the OS treats the various parts of the program as data, including the .text
section (those containing program code / machine code instructions).
For 8-bit data bytes, all possible bit patterns (all possible values) are used to convey meaning — e.g. they differentiate between 256 different ascii symbols, or represent numbers from 0..255 or -128..127 or, represent parts of some larger word encoding. Since instructions are data, there's no inherent way for a processor or anyone else to differentiate between them.
That being said, however, modern operating systems and processors allow protection of sections, like .text
, such that writing to that is prevented.
Is there another way to distinguish between these ?? [Without Metadata]
No, metadata is the approach.
If a processor can be fed instructions when it should be seeing data, it will happily go about executing the passed instructions.
This is cumbersome wording. I don't know what it means to say "it should be seeing data". I might say when the program is fooled into executing what the program intended as data.
But modern processors and operating systems have techniques that thwart this. Marking the runtime/call stack as non-executable is one such approach. The idea is to carry some of that program metadata over into the runtime using hardware features that effectively tag some memory regions with execute permission (or not). Tagging regions or pages is more efficient than tagging individual machine code instructions or individual data bytes.
See more here: https://en.wikipedia.org/wiki/Buffer_overflow_protection